Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

UnifiedFFI - A common language for the outside world

545 views

Published on

UnifiedFFI - A common language for the outside world
Video: https://youtu.be/418eEvCiepU
Fri, August 26, 11:45am – 12:30pm

First Name: Esteban
Last Name: Lorenzano
Email: estebanlm@gmail.com
Title: UnifiedFFI - A common language for the outside world
Type: Talk

Abstract: UnifiedFFI is a new foreign function interface who aims to reunite the best of all previous implementations into a single common API. Developed
for the new SpurVM, it keeps the simplicity of NativeBoost function calls syntax but with the backbone of the more easy to maintain FFIPlugin.

Bio: Esteban Lorenzano, 44 years. Programmer since ever, Full-time Smalltalker since 2007 and Pharo enthusiast since almost its every beginning, after
owning his own company and spend some years teaching at different universities in Argentina, he currently leads de development of Pharo itself, at the
RMoD team of INRIA (France)

Published in: Software
  • Video: https://youtu.be/418eEvCiepU
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

UnifiedFFI - A common language for the outside world

  1. 1. UnifiedFFI A common language to talk with the outside world Now with dem o!
  2. 2. Esteban Lorenzano (The stabilisation fairy)
  3. 3. What is UnifiedFFI • A front-end to express Foreign Function Interface (FFI) calls in Pharo. • Uses ThreadedFFIPlugin, but should be able to plug others in the future. • It shares same philosophy as NativeBoost ‣ keep as much as possible in the image ‣ no need to modify VM to add functionality ‣ But it is not ASM: Just plain Smalltalk.
  4. 4. But, what happened with NativeBoost? • It was not working on Spur • It was hard to maintain (and we need a different implementation for each architecture) • Since we were using NB exclusively for FFI, we decided to replace it with a different one, using the VM plugin
  5. 5. UnifiedFFI goals • Keep NativeBoost syntax ‣ Because is cool :) ‣ Provide backward compatibility for most uses • Enhance documentation and self-documentation • Be the unified base for future FFI backends implementations
  6. 6. How does a call looks like? char *getenv(const char *) getEnv: variable ^ self ffiCall: #( String getenv( String variable )) module: LibC (People who know NativeBoost will find this very familiar….)
  7. 7. How does a call looks like? char *getenv(const char *) getEnv: variable ^ self ffiCall: #( String getenv( String variable )) module: LibC A regular Pharo method with one argument
  8. 8. How does a call looks like? char *getenv(const char *) getEnv: variable ^ self ffiCall: #( String getenv( String variable )) module: LibC A literal array to represent C function
  9. 9. How does a call looks like? char *getenv(const char *) getEnv: variable ^ self ffiCall: #( String getenv( String variable )) module: LibC Types annotation used to generate marshalling code
  10. 10. How does a call looks like? char *getenv(const char *) getEnv: variable ^ self ffiCall: #( String getenv( String variable )) module: LibC The value to be passed when calling out
  11. 11. How does a call looks like? char *getenv(const char *) getEnv: variable ^ self ffiCall: #( String getenv( String variable )) module: LibC The library to lookup C function
  12. 12. FFILibrary • A very simple abstraction to define module names that can be different each platform. • Can be used also as a place to store C function definitions (like a real library :) ).
  13. 13. FFILibrary: LibC FFILibrary subclass: #LibC LibC>>unixModuleName ^ ‘libc.so.6' LibC>>macModuleName ^ ‘libc.dylib' LibC>>win32ModuleName ^ ‘msvcrt.dll' LibC>>memCopy: src to: dest size: n ^ self ffiCall: #(void *memcpy(void *dest, const void *src, size_t n))
  14. 14. Insights to UnifiedFFI getEnv: variable ^ self ffiCall: #( String getenv( String variable )) module: LibC
  15. 15. Insights to UnifiedFFI getEnv: variable ^ self ffiCall: #( String getenv( String variable )) module: LibC 1.Generate bytecodes for marshalling 2.Re-send the method execution char *getenv(const char *)
  16. 16. How does a call looks like? (bytecode version) char *getenv(const char *) 21 <20> pushConstant: <cdecl: char* 'getenv' (char*) module: 'libc.dylib'> 22 <10> pushTemp: 0 23 <8A 81> pop 1 into (Array new: 1) 25 <E1> send: invokeWithArguments: 26 <7C> returnTop
  17. 17. Types • Support for standard C types: int, float, etc. • Support for type aliases (map a name to one of the defined types) • Complex types: • FFIExternalObject: External addresses (objects) • FFIOpaqueObject: Opaque C types/structures • FFIExternalStructure • FFIExternalArray, FFITypeArray • FFIExternalEnumeration • FFIExternalValueHolder: Buffers (to pass referenced data, e.g. “double *”) • FFIConstantHandle: Windows HANDLE (constant addresses)
  18. 18. FFIExternalObject (1) AthensSurface subclass: #AthensCairoSurface uses: TCairoLibrary instanceVariableNames: 'handle context builder id ftFontRenderer session' classVariableNames: '' poolDictionaries: 'AthensCairoDefs' package: ‘Athens-Cairo' cairo_surface_t * cairo_image_surface_create (cairo_format_t format, int width, int height);
  19. 19. FFIExternalObject (2) AthensCairoSurface class>>primImage: aFormat width: aWidth height: aHeight ^self ffiCall: #(AthensCairoSurface cairo_image_surface_create ( int aFormat, int aWidth, int aHeight) ) cairo_surface_t * cairo_image_surface_create (cairo_format_t format, int width, int height);
  20. 20. FFIExternalObject (3) AthensCairoSurface>>getDataPtr "get a pointer to surface bitmap data" ^self ffiCall: #( void* cairo_image_surface_get_data ( self ) ) unsigned char * cairo_image_surface_get_data (cairo_surface_t *surface);
  21. 21. FFICallback callback := FFICallback signature: #(int (const void *arg1, const void *arg2)) block: [ :arg1 :arg2 | ((arg1 doubleAt: 1) - (arg2 doubleAt: 1)) sign ]. int (*compar)(const void*,const void*)
  22. 22. FFICallback callback := FFICallback signature: #(int (const void *arg1, const void *arg2)) block: [ :arg1 :arg2 | ((arg1 doubleAt: 1) - (arg2 doubleAt: 1)) sign ]. int (*compar)(const void*,const void*) A literal array to represent C anonymous function
  23. 23. FFICallback: qsort Cqsort>>primQsort: array with: count with: size with: compare self ffiCall: #(void qsort (FFIExternalArray array, size_t count, size_t size, FFICallback compare)) module: LibC Cqsort>>example | array callback | array := FFIExternalArray newType: 'double' size: 100. 1 to: 100 do: [ :i | array at: i put: (100 atRandom asFloat) ]. callback := FFICallback signature: #(int (const void *arg1, const void *arg2)) block: [ :arg1 :arg2 | ((arg1 doubleAt: 1) - (arg2 doubleAt: 1)) sign ]. self primQsort: array with: 100 with: (FFIExternalType sizeOf: ‘double’) with: callback.
  24. 24. Status • Feature complete (but I keep adding stuff when requested) • Documentation ongoing • Still can accept a lot of optimisations (but that will be for versions 1.x)
  25. 25. Summary • Replace for NativeBoost keeping its philosophy • Simple Callout/Callback system • Very easy to extend (no need of ASM knowledge) • Is ready to use in Pharo 5.0
  26. 26. Thanks! Smalltalk quitSession.

×