From 71dd4c5f718bf7cb6144cf4fcb832a46044a97ca Mon Sep 17 00:00:00 2001 From: StephaneDucasse Date: Wed, 29 Oct 2014 11:49:55 -0500 Subject: [PATCH] adding NativeBoost --- NativeBoostX11/NativeBoostX11.pillar | 1147 ++++++++++++++++++++ NativeBoostX11/figures/displayInstance.pdf | Bin 0 -> 16517 bytes NativeBoostX11/figures/fourWindows.pdf | Bin 0 -> 19757 bytes NativeBoostX11/figures/oneWIndow.pdf | Bin 0 -> 16568 bytes NativeBoostX11/figures/xeyes.pdf | Bin 0 -> 29845 bytes pillar.conf | 1 + support/templates/book.latex.template | 2 + 7 files changed, 1150 insertions(+) create mode 100644 NativeBoostX11/NativeBoostX11.pillar create mode 100644 NativeBoostX11/figures/displayInstance.pdf create mode 100644 NativeBoostX11/figures/fourWindows.pdf create mode 100644 NativeBoostX11/figures/oneWIndow.pdf create mode 100644 NativeBoostX11/figures/xeyes.pdf diff --git a/NativeBoostX11/NativeBoostX11.pillar b/NativeBoostX11/NativeBoostX11.pillar new file mode 100644 index 0000000..01f0317 --- /dev/null +++ b/NativeBoostX11/NativeBoostX11.pillar @@ -0,0 +1,1147 @@ +! NativeBoost Recipes: The X11 Journey + +There is nothing better than real examples to learn. In this chapter, we will create some bindings to X11 Xlib. This chapter was written by L. Laffont during a visit in the RMOD team and largely revisited by S. Ducasse and I. Stasenko. + + +!! Some documentation + +First, you may need some documentation and pointers: + +- the Xlib documentation: *http://www.x.org/docs/X11/xlib.pdf* +- the NativeBoost project on SmalltalkHub: *http://www.smalltalkhub.com/#!/~Pharo/NativeBoost* +- the paper ''Language-side Foreign Function Interfaces with NativeBoost'': *http://hal.archives-ouvertes.fr/docs/00/84/07/81/PDF/paper.pdf* + + +!! Must read before start! + +Before doing anything we should check first that we can link with the library that we want to use, here X11. + +First, as the Pharo VM runs in 32-bit, the libraries you want to bind to (and their dependencies) must be compiled for 32-bit as well. There are plans to have a 64 bits version of the Pharo VM, and as soon as this happens there will be a 64-bit version of NativeBoost. Major Linux distributions provide 32-bit versions of their packages. For example, on ArchLinux 64-bit, when you search for the ==libx11== package: + +[[[language=shellcommands +$ pacman -Ss libx11 +extra/libx11 1.6.1-1 [installed: 1.6.0-1] + X11 client-side library +multilib/lib32-libx11 1.6.1-1 + X11 client-side library (32-bit) +]]] + +To create the bindings, we need to install the 32-bit package: + +[[[language=shellcommands +$ pacman -S multilib/lib32-libx11 +]]] + +and the library will be found at ==/usr/lib32/libX11.so==. + +Sometimes the library isn't available for 32-bit, so you will have to build it. Often libraries rely on autotools for the compilation and it's just a story of setting ==-m32== flags for ==gcc==. Here's the example for ==YAZ== library: + +[[[language=shellcommands +$ wget http://ftp.indexdata.dk/pub/yaz/yaz-4.2.63.tar.gz +$ tar -xvzf yaz-4.2.63.tar.gz +$ cd yaz-4.2.63 +$ ./configure CFLAGS="-m32" LDFLAGS="-m32" +$ make +$ sudo make install +]]] + +We can check that a library is 32-bit with the ==file== command. Here, the output mentions that the library is indeed 32-bit, which is compatible with the current implementation of NativeBoost and the Pharo VM. + +[[[language=shellcommands +$ file /usr/local/lib/libyaz.so.4.0.0 +/usr/local/lib/libyaz.so.4.0.0: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=479fbc7e495cb53600f145cf575dc1f176703c20, not stripped +]]] + +We also have to make sure that all dependent libraries are found using ==ldd== command: + +[[[language=shellcommands +$ ldd /usr/local/lib/libyaz.so.4.0.0 + linux-gate.so.1 (0xf773a000) + libgnutls.so.28 => /usr/lib32/libgnutls.so.28 (0xf745d000) + libexslt.so.0 => not found + libxslt.so.1 => /usr/lib32/libxslt.so.1 (0xf7417000) +]]] + +Here ==libexslt.so.0== is not found, so we have to make sure it is present, 32-bit and on the right path. On the system I use, ==libexstl== has been installed on ==/usr/local/lib/== and I should either move them to ==/usr/lib32==, or set the environment variable ==LD_LIBRARY_PATH==. + +[[[language=shellcommands +$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib +$ ldd libyaz.so + linux-gate.so.1 (0xf7728000) + libgnutls.so.28 => /usr/lib32/libgnutls.so.28 (0xf744b000) + libexslt.so.0 (0xf7434000) +]]] + +To add a custom directory globally to ==LD_LIBRARY_PATH==, just add it in ==/etc/ld.so.conf==. + +At last, remember that we can write bindings for C libraries easily, other languages such as ==C\+\+== are beyond the scope of this chapter +because ==C\+\+== does not have a standard binary interface. It means that to call a ==C\+\+== library you have to know the OS version, the ==C\+\+== compiler version +and may be some other information. Usually to call ==C\+\+== library, one practice is to wrap it in a C-layer and call this C layer. + + +!!! To install X11 on Mac + +If you are on Mac OSX, your best bet to get X11 working is to download and install the package from *http://xquartz.macosforge.org*. Alternatively, if you're using *Macports>http://www.macports.org*, you can try installing their packages ==xorg-libX11== and ==xorg-server==. + +To check X11 is installed and works, open a new shell and run ==xeyes==. You should get the famous eye application looking at you. + + +!! A first NativeBoost binding + +While you follow along, do not forget to save your image quite often, crashes easily occur in this field! + + +!!! Connecting to the X Server + +Before our program can use a display, we must establish a connection to the X server using ==XOpenDisplay==. +Taking from the documentation: "==The XOpenDisplay()== function returns a Display structure that serves as the connection to the X server and that contains all the information about that X server. ==XOpenDisplay()== connects your application to the X server through TCP or DECnet communications protocols, or through some local inter-process communication protocol." + +The signature in ==Xlib.h== (that you should find at ==/usr/include/X11/Xlib.h== or ==/usr/X11/include/X11== on Mac) is: + +[[[ +Display *XOpenDisplay(char *display_name); +]]] + +First, we can check that Pharo and NativeBoost could load the Xlib library and find the function. In a workspace, inspect the result of: + +[[[ +self nbGetSymbolAddress: 'XOpenDisplay' module: '/your/path/to/32-bit/libX11.so' +]]] + +That should answer something like ==@ 16rF71D14D0==, the address of the function. If ==nil== is answered, then something is wrong and you should refer to previous section. Else, we can go further! +You can use ==find . -name '*X11*.dylib'== to look for libraries for example. + + +The function ==XOpenDisplay== takes a pointer on char as parameter (thus a String) and returns a pointer on a ==Display==. +We could define all the function in a large class representing the library, but we will apply an object-oriented decomposition of the X11 world. Therefore, we need to define a class that will hold an handle for ==Display==. We can do this by creating a subclass of ==NBExternalObject== as follows: + +[[[ +NBExternalObject subclass: #NBXLibDisplay + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'NBXLib' +]]] + +For each NativeBoost entity we have to define the method ==nbLibraryNameOrHandle== that answers the path to the module. +To avoid to define multiple times this method, we can define a ==Trait== to be used by all our ==NBXLib== package classes: + +[[[ +Trait named: #TNBXLibLibrary + uses: {} + category: 'NBXLib' + +TNBXLibLibrary class>>nbLibraryNameOrHandle + ^ '/your/path/to/32-bit/libX11.so' + +TNBXLibLibrary>>nbLibraryNameOrHandle + ^ self class nbLibraryNameOrHandle +]]] + +Then we update the ==NBXLibDisplay== class definition to: + +[[[ +NBExternalObject subclass: #NBXLibDisplay + uses: TNBXLibLibrary + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'NBXLib' +]]] + +We can now create the binding for the function ==XOpenDisplay==. +As it will be used to create a new ==NBXLibDisplay== instance, we define the primitive on the class side. +We define the message ==open:== that will call the X11 primitive as follows: + +[[[ +NBXLibDisplay class>>open: displayName + + ^self nbCall: #(NBXLibDisplay XOpenDisplay (char * displayName)) +]]] + +Note that we specify in the signature that the function returns an ==NBXLibDisplay== (i.e., an instance of the class itself) while the C function mentioned a ==Display== type. NativeBoost is handling that for us. + +Then we can try to open the default X display (number 0): + +[[[ +NBXLibDisplay open: ':0' +]]] + +This expression should answer a new instance of ==NBXLibDisplay==. If ==displayName== argument is ==NULL==, XOpenDisplay defaults to the value of the ==DISPLAY== environment variable. As it's often what we want, we can add a new class method named ==open== defined as follows: + +[[[ +NBXLibDisplay class>>open + + + ^self nbCall: #(NBXLibDisplay XOpenDisplay (nil)) +]]] + +We can then open the default display with the following expression: + +[[[ +NBXLibDisplay open +]]] + +When you inspect the result of the last expression you should obtain Figure *displayInstance*. + ++Inspecting NBXLibDisplay open>file://figures/displayInstance.pdf|width=40|label=displayInstance+ + + +!! About NativeBoostPlugin primitives + +Now it is time to explain what we did a bit. Let'us analyse what we wrote. + +We wrote basically two lines: + +[[[ + +]]] + +The first line is a ==pragma== (named ==primitive:module:error:==) that tries to execute a primitive function. +As any primitive, it only execute the body of the method (in this case the send of ==nbCall:==) if the primitive fails. + +So here first the ==primitiveNativeCall== of ==NativeBoostPlugin== tries to perform the foreign +call by executing assembly code. If it fails (which it always will the first time because the assembly code +has not been generated yet), an ==errorCode== is returned and the body of the method is executed. This evaluation will kick +in the assembly generation and next time we will call this method, the primitive will not fail. + + +Now let'us look at the second line. +[[[ +^self nbCall: #(NBXLibDisplay XOpenDisplay (char * displayName)) +]]] +The second line defines the call we want to perform. +Here, ==nbCall:== will parse the array and produce the machine code to perform the function call to ==XOpenDisplay==. + + +!!! Mapping C - Pharo + +Now remember that the actual C signature is: + +[[[ +Display *XOpenDisplay(char *display_name); +]]] + +Let's have a look at how NativeBoost maps C to Pharo and vice versa. First, the message ==nbCall:== parses the function signature as a literal array. Then, NativeBoost automatically does the marshalling between C and Pharo. + +Many primitive C types like ==int== and ==void *== are fine as is. However, types with multiple-word names, like ==unsigned int==, must be replaced because the NativeBoost parser ==NBFnSpecParser== expects single-word type names. So instead of writing ==unsigned int==, we use ==uint==. Here are some primitive types and their mapping to Pharo types. +- ==uint== or ==int==: ==Integer== +- ==bool==: ==Boolean== +- ==float==: ==Float== +- ==char==: ==Character== + +See below for a longer list. + + +!!! About C strings + +Usually the C idiom to represent a string datatype is to declare a pointer to the first character of a null-terminated array - In C there is no formal definition of what a string is. Now when we want to call functions expecting ==char *==, care must be taken. Let us see why. + +We should pay attention because a ==char *== datatype is not necessarily a string. It could simply be a pointer. Therefore, read the documentation of the library to make sure +that the function argument in question is expecting a string and not just a pointer to a char value. + +For null-terminated strings, NativeBoost provides a special type named ==String==. Using this type, the value is automatically converted between a Pharo ==ByteString== and a C null-terminated string. + +When you know that your library is really expecting a C null-terminated string, it is safer to use ==String== in a NativeBoost type declaration than ==char *== because ==char *== is just managed as a simple pointer and does not make sure that the string is null-terminated. + +So we can change ==NBXLibDisplay class>>open== to use ==String==: + +[[[ +^self nbCall: #(NBXLibDisplay XOpenDisplay (String displayName)) +]]] + + +!!! Supported Types + +Here is the list of types NativeBoost supports by default. We show the C names as well as the NativeBoost equivalent. + +!!!! Booleans +- ==bool NBBool== + +!!!! Fixed size integer types +Here the byte order is platform dependent. +- ==int8 NBInt8== +- ==uint8 NBUInt8== +- ==int16 NBInt16== +- ==uint16 NBUInt16== +- ==int32 NBInt32== +- ==uint32 NBUInt32== +- ==int64 NBInt64== +- ==uint64 NBUInt64== + +!!!! Aliases to common C compiler types +Some of them are platform dependent, some are not... because the C standard does not fully specify it. + +- ==signedByte int8== +- ==unsignedByte int8== +- ==signedShort int16== +- ==unsignedShort uint16== +- ==signedChar int8== +- ==unsignedChar uint8== +- ==schar int8== +- ==uchar uint8== +- ==signedLong int32== +- ==unsignedLong uint32== +- ==sbyte int8== +- ==byte uint8== +- ==short int16== +- ==ushort uint16== +- ==long int32== +- ==ulong uint32== +- ==longlong int64== +- ==ulonglong uint64== +- ==uint uint32== +- ==int int32== + +!!!! Unsigned for sizes +Usually the same size as the platform's word size. It is unsigned integer types having the same length as a pointer. +- ==size_t NBSizeT== + +!!!! Character type + +- ==Character NBCharacterType== +- ==char NBCharacterType== + +Note that ==Character== and ==char== are special. NativeBoost converts between C character and Pharo Character instances. +If you just want an unsigned integer value, use ==uint8== or ==int8== instead (The 8 indicates that this is one byte). + +!!!! Floats fixed-size +Here again such types have platform-dependent byte order. + +- ==float16 NBFloat16== +- ==float32 NBFloat32== +- ==float64 NBFloat64== +- ==float128 NBFloat128== + +!!!! Floats common type names +NativeBoost provides some aliases to C type names. + +- ==float float32== +- ==double float64== +- ==shortFloat float16== + + +!!! Customizing Type Resolution + +We can also affect the way NativeBoost resolves types. This is useful for preserving C function signatures. If you remember, we had to change the original signature from +[[[ +Display *XOpenDisplay(char *display_name); +]]] + +to +[[[ +NBXLibDisplay XOpenDisplay (char * displayName) +]]] + +But we'd like to write: +[[[ +^self nbCall: #(Display XOpenDisplay (String displayName)) +]]] + + +We have three options to specify which class to use for the ==Display== type (listed in look-up order): + +- class variable +- shared pool +- class + +If we decide to use a class variable, we change the definition of ==NBXLibDisplay== to: + +[[[ +NBExternalObject subclass: #NBXLibDisplay + uses: TNBXLibLibrary + instanceVariableNames: '' + classVariableNames: 'Display' + poolDictionaries: '' + category: 'NBXLib' +]]] + +and then initialize the ==Display== class variable. Note that the value is a symbol because the array contains literal values. +Do not forget to execute the expression ==NBXLibDisplay initialize== once you define the method: + +[[[ +NBXLibDisplay class>>initialize + Display := #NBXLibDisplay +]]] + + +Now when we run ==NBXLibDisplay open==, NativeBoost will map the ==Display== return type to the ==NBXLibDisplay== class. + +As we often need to share these mappings between several classes in our package, it is best to use shared pools. +We'll call it ==NBXLibTypes== and move the ==Display== class variable and its initializer there. + +Now all our code is: + +[[[ +Trait named: #TNBXLibLibrary + uses: {} + category: 'NBXLib' + +TNBXLibLibrary class>>nbLibraryNameOrHandle + ^ '/your/path/to/32-bit/libX11.so' + +TNBXLibLibrary>>nbLibraryNameOrHandle + ^ self class nbLibraryNameOrHandle + +SharedPool subclass: #NBXLibTypes + instanceVariableNames: '' + classVariableNames: 'Display' + poolDictionaries: '' + category: 'NBXLib' + +NBXLibTypes class>>initialize + Display := #NBXLibDisplay. + +NBExternalObject subclass: #NBXLibDisplay + uses: TNBXLibLibrary + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: 'NBXLibTypes' + category: 'NBXLib' + +NBXLibDisplay class>>open + + ^self nbCall: #(Display XOpenDisplay (nil)) + +NBXLibDisplay class>>open: displayName + + ^self nbCall: #(Display XOpenDisplay (String displayName)) +]]] + + +!!! A word about NBExternalObject + +Instances of ==NBExternalObject== represent an external object of one kind, provided by some external library/function. An instance holds a handle, which is used to identify the external object when this instance is passed as an argument, or when it is used as a return type in a function signature. + +A typical usage of ==NBExternalObject== is to create a subclass, and then use that subclass name directly in function signatures. This is what we did previously. + +We defined a subclass +[[[ +NBExternalObject subclass: #NBXLibDisplay +]]] + +We then defined a primitive call. +[[[ +NBXLibDisplay class>>open + + ^self nbCall: #(NBXLibDisplay XOpenDisplay (nil)) +]]] +And we got an instance from that class. +[[[ +newObj := NBXLibDisplay open. +]]] + +Here, we assume that ==XOpenDisplay()== returns a handle (or pointer) to some opaque external structure. +Using an NBExternalObject subclass (i.e., NBXLibDisplay) as a return type in the function signature, +we are telling the code generator to automatically convert the return value into an instance of that class +and initialize its handle to the value returned by the function. + +When used as argument type, the ==handle== instance variable is passed to the external function. + +The main advantage of using an ==NBExternalObject== subclass as a type name for arguments is that it +provides type safety by checking that the incoming argument is an instance of your class, and nothing else. +Otherwise, the primitive will fail without calling the external function. + + +!! Self magic + +To close the connection to a Xlib Display, we should use the C function: + +[[[ +int XCloseDisplay(Display *); +]]] + + +Since we are in Pharo, we would like to have an oriented-object API instead of defining all C functions on class side +for example. So we would like to close the connection sending the message ==close== to an instance like +this: ==myDisplay close==. This means that we should be able to refer to the object that receives the message. +Here is the way to do it. Let's define an instance-side method in the class ==NBXLibDisplay==: + +[[[ +NBXLibDisplay>>close + + ^self nbCall: #(int XCloseDisplay(Display self)) +]]] + +We simply use ==self== to refer to the object itself. Even more, with ==self== we can omit the type and just write: + +[[[ +NBXLibDisplay>>close + + ^self nbCall: #(int XCloseDisplay(self)) +]]] + +Now we can open and close the display: + +[[[ +| display | +display := NBXLibDisplay open. +display close. +]]] + + +!! Let's start the real fun stuff! + +The goal of this section is to find our desktop application windows and then to move or resize them. Each window has properties attached, called Atoms. Each Atom type has a unique identifier. When your window manager follows the ==Extended Window Manager Hints (EWMH)== spec (this is the case for Gnome and KDE, see http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html), you can get all windows managed by the window manager using the Xlib C function ==XGetWindowProperty== for the Atom ==_NET_CLIENT_LIST_STACKING==. + + +First we need to find the identifier of the Atom ==_NET_CLIENT_LIST_STACKING== using the Xlib function ==XInternAtom==: +[[[ +Atom XInternAtom(Display* display, char* atom_name, Bool only_if_exists) +]]] + + +As we want to have a nice object-oriented API, we should separate the instance creation method and primitive on a new ==NXLibAtom== class. Let's start with the primitive. ==Atom== is defined in ==X.h== as: + +[[[ +typedef unsigned long Atom; +]]] + +So we should add the definition of the Atom mapping to our shared pool: + +[[[ +NBXLibTypes class>>initialize + Display := #NBXLibDisplay. + Atom := #ulong +]]] + +We should not forget to execute ==NBXLibTypes initialize== so that the new mapping is active. + +Now we can define a method ==atomNamed: aString== using the ==XInternAtom== primitive: + +[[[ +NBXLibDisplay>>atomNamed: aString + + ^self nbCall: #(Atom XInternAtom(self, String aString, true)) +]]] + +Note that we define the method on the instance side since we will invoke it on an existing object representing the display. +Here we give ==true== as the last argument so the Atom will be created if it does not exist. Note that for booleans we don't need to specify the type. + +You can check that this is working with the following expression: + +[[[ +NBXLibDisplay open atomNamed: '_NET_CLIENT_LIST_STACKING' +]]] + +It answers ==460== on our machine (this changes for each display). + + +!!! Getting the root window + +We need to get the root window of the display before querying any property on it, using the Xlib function ==XDefaultRootWindow==: +[[[ +Window XDefaultRootWindow(Display *display); +]]] + +Since we will want to send messages to ==Window==, let's create a class subclass of ==NBExternalObject==. + +[[[ +NBExternalObject subclass: #NBXLibWindow + uses: TNBXLibLibrary + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: 'NBXLibTypes' + category: 'NBXLib' +]]] + +We should also update the shared pool (do not forget to execute ==NBXLibTypes initialize==): +[[[ +NBXLibTypes class>>initialize + Display := #NBXLibDisplay. + Atom := #ulong. + Window := #NBXLibWindow. +]]] + +We can implement a method in ==NBXLibDisplay== to get the defaultRootWindow by calling the ==XDefaultRootWindow(Display *display)== function. Why don't you take a moment to define it by yourself before reading the following definition: + +[[[ +NBXLibDisplay>>defaultRootWindow + + ^self nbCall: #(Window XDefaultRootWindow(self)) +]]] + +The following expression should now answer an ==NBXLibWindow== instance: +[[[ +NBXLibDisplay open defaultRootWindow +]]] + + +As Xlib functions often need to access the display and the window for window manipulations, let's allow ==NBXLibWindow== to reference its display by adding an instance variable ==display== and accessor methods. + +[[[ +NBExternalObject subclass: #NBXLibWindow + uses: TNBXLibLibrary + instanceVariableNames: 'display' + classVariableNames: '' + poolDictionaries: 'NBXLibTypes' + category: 'NBXLib' + +NBXLibWindow>>display: aNBXLibDisplay + display := aNBXLibDisplay + +NBXLibWindow>>display + ^ display +]]] + +Then we rename the previous ==defaultRootWindow== to ==primitiveDefaultRootWindow== and move it to the 'private' protocol. Finally we define a new method ==defaultRootWindow== as follows: + + +[[[ +NBXLibDisplay>>defaultRootWindow + ^ self primDefaultRootWindow display: self ; yourself + +NBXLibDisplay>>primDefaultRootWindow + + ^self nbCall: #(Window XDefaultRootWindow(self)) +]]] + + +!! A more complex example: Getting properties +Now we will show how we can handle return values and other concerns needed to deal with more complex situations. +Xlib defines a generic function to get properties, ==XGetWindowProperty()==. It is a bit verbose and its signature is: +[[[ +int XGetWindowProperty ( + Display *display, + Window w, + Atom property, + long long_offset, + long long_length, + Bool delete, + Atom req_type, + Atom * actual_type_return, + int * actual_format_return, + unsigned long * nitems_return, + unsigned long * bytes_after_return, + unsigned char ** prop_return); +]]] + +- The three first parameters are easy: the display, the root window in our case, and the Atom ==_NET_CLIENT_LIST_STACKING==. +- For ==long_offset== and ==long_length==, they can be used to do a partial read of the properties. To keep things simple, we will get all of them, so ==0== for the offset and ==16rFFFF== for the length. Now, we don't care about ==bytes_after_return== for now. +- For the ==req_type==, we can use the Xlib constant ==AnyPropertyType==. We will handle the ==actual_type_return== and ==actual_format_return== in next section. + +The Atom ==AnyPropertyType== is a special Atom defined to 0. We can add it to the shared pool for later use: + +[[[ +NBXLibTypes class>>initialize + Display := #NBXLibDisplay. + Atom := #ulong. + AnyPropertyType := 0. +]]] + + +!!!! About returned values + +The last five arguments of the function ==XGetWindowProperty== are output parameters. They are locations provided by the user in which the library stores values. This is why they are specified as pointers. + +For the first four we can use a ByteArray buffer that is big enough to hold the returned data. In our case this is 4 bytes each as we will show in a moment. The NativeBoost declaration for ==actual_type_return==, ==actual_format_return==, ==nitems_return==, ==bytes_after_return== is simply: + +[[[ +Atom * actualType, int * actualFormat, ulong * nbItems, ulong * bytesAfterReturn +]]] + +The last argument requires a bit more attention. + + +!!! Dealing with pointer output arguments + +The ==prop_return== is defined as ==unsigned char **==, literally a pointer on a pointer. What this C idiom wants to convey is that the function is expecting a pointer where it will store the pointer to the returned data. From that perspective, the signature ==char **== could have been expressed as ==void **==. + +To deal with such an idiom, NativeBoost provides the ==NBExternalAddress== class to hold an external address. + +Now let's define the primitive that will retrieve the properties calling the ==XgetWindowProperty()== function. + +[[[ +NBXLibWindow>>primGetWindowProperty: anAtom + offset: offset + length: length + delete: delete + requiredType: requiredType + intoActualType: actualType + actualFormat: actualFormat + numberOfItems: nbItems + bytesAfterReturn: bytesAfterReturn + data: data + + + ^self nbCall: #(int XGetWindowProperty(Display display, self, Atom anAtom, long offset, long length, bool delete, Atom requiredType, Atom * actualType, int * actualFormat, ulong * nbItems, ulong * bytesAfterReturn, NBExternalAddress * data )) +]]] + +Here we see that we use ==NBExternalAddress * data== in a signature. By default there is no difference whether you specify ==anytype*== or ==anytype**== or ==anytype***== etc in function signature, because NativeBoost treats all pointer types similarly: it just checks that value you passed to the function can be converted to a pointer. + +For instance, if we use ==void *== in the function signature, we can pass any of following: +- any variable-byte instance (==ByteArray==, ==ByteString== etc) +- any variable-word instance (==WordArray== etc) +- an instance of ==NBExternalAddress==. For variable-sized objects a pointer to the first indexable element will be passed, and for instances of ==NBExternalAddress== the actual value will be passed. + +But if we explicitly specify ==NBExternalAddress *== as an argument type, in this case NativeBoost will accept only an instance of ==NBExternalAddress== +as a valid argument (no variable-sized objects), and instead of passing a value held by an ==NBExternalAddress== instance, it will pass a pointer to a location where this value is stored. + +As result, after calling the function, it will store an output value in the provided ==NBExternalAddress== instance, which we're free to use later. + + +!!!! NBExternalAddress vs. void +We use ==NBExternalAddress *== and not ==void *== because: using ==void *== we could pass a byte +array and we would get back the address stored inside the byte array. And from these four bytes we would have to construct an +address. In addition, using ==NBExternalAddress== provides extra safety because NativeBoost will refuse to perform a call when +given something else than a ==NBExternalAddress== instance. + + +!!! Dealing with Arrays of C type values + +So far we defined a method (primitive) to call the C function but we did not define how to perform the actual call. Now we explain the next steps to arrive to this point. + +Communicating with a C library often requires dealing with arrays of certain datatype (ints, floats etc). +There is no direct correspondence between Pharo arrays (array of objects) and arrays in C (array of certain datatype values), +and NativeBoost provides no implicit conversions between them because there is no magic. +While for most basic types, the automatic conversion can be done (integers, floats etc), for any more complex datatypes, +like array of structures it is impossible. +Moreover, an automatic conversion between C arrays and instances of ==Array== would require copying/converting data to represent +each array element as an object (which is expensive if done systematically). Such automatic conversion requires knowledge about the +array size beforehand, which also is not always the case. + +In case, if we don't need accessing array's elements and just need a space to store an array as a whole, +we can just use instances of ==ByteArray== big enough to accommodate C array of requested size (after all, anything held in computer memory is just a bunch of bytes). +And while this is cheap and a simple way to hold external data, there is a downside, when it comes to accessing or enumerating elements of such C array: +Indeed ==ByteArray== does not provide helpers to access the elements other than bare bytes in an easy way. It means that it can cumbersome to retrieve the elements of C array stored in the ==ByteArray==. + +NativeBoost provides a way to operate with arrays of C type using ==NBExternalArray==. +Let us look at a simple example before going back to our X11 tutorial. + +!!!! Array of ==int== + +Imagine that we want to work with arrays of int (==int [ ]==). We subclass the class ==NBExternalArray== and redefine the class side ==initialize== method to initialize the array element type: + +[[[ +NBExternalArray subclass: #NBXArrayOfInts + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'NBXLib' + +NBXArrayOfInts class>>initialize + self initElementType: 'int' +]]] + +Before using the class, you should not forget to initialize it by executing ==NBArrayOfInts initialize==. + + +Now we can create an array of 10 ints as follows: + +[[[ +(NBXArrayOfInts new: 10) + returns a NBXArrayOfInts(0 0 0 0 0 0 0 0 0 0) +]]] + +Since ==NBExternalArray== is a subclass of ==ArrayedCollection==, we can use it as a regular array responding to the normal messages of Array like collections. +The only difference is that the elements has fixed type. If we pass invalid objects as argument of a ==at:put:== message, +an error will be raised. + +The following code snippet shows how you can get such errors: +[[[ +(NBXArrayOfInts new: 10) at: 10 put: -1 + +(NBXArrayOfInts new: 10) at: 10 put: nil "raises an error" +]]] + +!!!! Anonymous classes +In certain situations, it is tedious to have to define a class for each datatypes. +NativeBoost supports the creation on the fly of anonymous classes using the message ==ofType:==. +Here is the equivalent of the previous one: + +[[[ +myClass := NBExternalArray ofType: 'int'. +myClass new: 10. +... +]]] + + +!! Handling a single C value with NBExternalTypeValue + +Similar to ==NBExternalArray==, NativeBoost proposes ==NBExternalTypeValue== which instance of which holds a single value of a concrete C type. +Using sub instances of ==NBExternalTypeValue== is particularly handy when dealing with output parameters of functions (as we will see in the next Section). + +For example, to define an output parameter of an int type, first define a subclass of ==NBExternalTypeValue==, then define the class method ==initialize== as follows: + +[[[ +NBExternalTypeValue subclass: #NBXIntValue + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'NBXLib' + +NBXIntValue class>>initialize + "self initialize" + self initValueType: 'int' +]]] + +Of course, do not forget to initialize the class (==NBXIntValue initialize==) before using it. + +Now we can set and access the value using the messages ==value== and ==value:== for instances of the newly created class. NativeBoost generates those accessors automatically. + +[[[ +(NBXIntValue new value: 33) value +]]] + +Now we can pass instances of this class as a output parameter to function which expects a pointer to an int. Imagine that we have a C function with the signature ==foo(int * i)== and its Pharo binding ==foo:== method defined as follows: + +[[[ +foo: aValue + + + ^self nbCall: #(void foo(int * aValue)) +]]] + +We can simply create an instance of NBXIntValue and pass it to the function. +[[[ +intValue := NBXIntValue new. +self foo: intValue + +intValue value "read the value set by a function" +]]] + +Note during the call, the function foo() stores an int at the given address (address represented by the instance of ==NBXIntValue==). +Then we can retrieve the value of this stored int as a Pharo ==Integer== sending the message ==value== to ==intValue==. + +!!!! Note +Before the introduction of ==NBExternalTypeValue==, you would had to do the following to get the same example working. + +[[[ +intValueBuffer := ByteArray new: 4. +self foo: intValueBuffer. +value := intValueBuffer nbUInt32AtOffset: 0. +]]] + + +!!!! Anonymous classes again +Again in certain situations, it is tedious to have to define a class for each datatype, especially +when there are way too many as in some libraries. NativeBoost supports the creation on the fly of +anonymous classes using the message ==ofType:==. Here is the equivalent of the previous one: + +[[[ +myClass := NBExternalTypeValue ofType: 'int'. +myClass new value: 10. +... +]]] + +Please note that the ==ofType:== expression creates a fresh anonymous subclass each time it is invoked. +Since it is expensive, it is recommended to store it in some kind of class variable and reuse the resulting class. + + +!! Back to X11 +Now we are ready to get write our method to access the existing windows. +Remember that we needed to get a way to return a collection of windows for the last argument. + +Let us define a new class to handle arrays of windows. We subclass ==NBExternalArray== and we +define the class side ==initialize== method as we did previously. + +[[[ +NBExternalArray subclass: #NBXLibArrayOfWindows + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'NBXLib' + +NBXLibArrayOfWindows class>>initialize + self initElementType: 'NBXLibWindow' +]]] + +Do not forget to execute ==NBXLibArrayOfWindows initialize==. + + +Now let us define a method ==managedWindows== to access all the currently display windows. +We use two instances of ==NBXIntValue==, one to represent the returned number of items and a dummy one for values we do not use. + +[[[ +NBXLibWindow>>managedWindows + | numberOfItems dataPtr dummy | + numberOfItems := NBXIntValue new. + dummy := NBXIntValue new. + dataPtr := NBExternalAddress new. + + self primGetWindowProperty: (display atomNamed: '_NET_CLIENT_LIST_STACKING') + offset: 0 + length: 16rFFFF + delete: false + requiredType: AnyPropertyType + intoActualType: dummy + actualFormat: dummy + numberOfItems: numberOfItems + bytesAfterReturn: dummy + data: dataPtr. + + "Fetch all the windows" + ^ (NBXLibArrayOfWindows onAddress: dataPtr size: numberOfItems value) +]]] + +Note that we will improve this method because it has some shortcomings. But first have fun and try the following expression. +You should get all the windows managed by your window manager (including docks and task bars) +and get an inspector as shown in the following Figure *Inspecting*. + +[[[ +NBXLibDisplay open defaultRootWindow managedWindows inspect +]]] + ++Inspecting the open X11 windows>file://figures/fourWindows.pdf|width=40|label=Inspecting+ + +Now let us explain ==(NBXLibArrayOfWindows onAddress: dataPtr size: numberOfItems value)==. +This message returns an array of the given size located on an address in memory. +The type of this array elements are C Window opaque type. It means that the array contains only handles to some windows. +Those handles on the Pharo side are represented as ==NBXLibWindow== instances, since we define an array (class ==NBXLibArrayOfWindows== ) whose elements are of +type ==NBXLibWindow==. + +When we read a particular element like when using the message ==at:== or ==do:==, each time NativeBoost +will convert the handle in a fresh ==NBXLibWindow== object. This conversion can be costly. + +To perform the conversion only once, i.e., to turn an array of handles into an array of ==NBXLibWindow== instances, +we send the message ==asArray== to +the ==(NBXLibArrayOfWindows onAddress: dataPtr size: numberOfItems value)==. +Now we can at the Pharo level connect a window with its display object. This is what we do with the last do statement of the method. + +[[[ +NBXLibWindow>>managedWindows + + | numberOfItems dataPtr dummy | + numberOfItems := NBXIntValue new. + dummy := NBXIntValue new. + dataPtr := NBExternalAddress new. + + self primGetWindowProperty: (display atomNamed: '_NET_CLIENT_LIST_STACKING') + offset: 0 + length: 16rFFFF + delete: false + requiredType: AnyPropertyType + intoActualType: dummy + actualFormat: dummy + numberOfItems: numberOfItems + bytesAfterReturn: dummy + data: dataPtr. + + "Fetch all the windows and init their display reference" + ^ (NBXLibArrayOfWindows onAddress: dataPtr size: numberOfItems value) asArray + do: [ :aWindow | aWindow display: display ] +]]] + + +!!! Memory Housekeeping + +The documentation of X11 says that we should free the memory allocated for retrieved data once we no longer need it. +Since there is no garbage collector in C, each time we will call this function we will create a memory leak. +The documentation says that we should use the ==XFree()== function. Therefore we going to define the ==free:== method as follows. + +[[[ +NBXLibDisplay>>free: aPointer + + + ^self nbCall: #(void XFree (void* aPointer)) +]]] + +We define ==free:== in ==NBXLibDisplay== because display plays a central role in the window management with X11. But we could have +implement it in ==NBXLibWindow==. Now we redefine the ==managedWindows== method into its final form. + +[[[ +NBXLibWindow>>managedWindows + + | numberOfItems dataPtr dummy result | + numberOfItems := NBXIntValue new. + dummy := NBXIntValue new. + dataPtr := NBExternalAddress new. + + self primGetWindowProperty: (display atomNamed: '_NET_CLIENT_LIST_STACKING') + offset: 0 + length: 16rFFFF + delete: false + requiredType: AnyPropertyType + intoActualType: dummy + actualFormat: dummy + numberOfItems: numberOfItems + bytesAfterReturn: dummy + data: dataPtr. + + "Fetch all the windows and init their display reference" + result := (NBXLibArrayOfWindows onAddress: dataPtr size: numberOfItems value) asArray + do: [ :aWindow| aWindow display: display ]. + display free: dataPtr. + ^ result +]]] + + +!! I like to move it, move it + +Now the last move. To move and resize windows, Xlib defines the function ==XMoveResizeWindow== defined as follow: + +[[[ +int XMoveResizeWindow(Display * display, Window w, int x, int y, unsigned int width, unsigned height) +]]] + +That should be straightforward to define it on our window class: +[[[ +NBXLibWindow>>x: x y: y width: width height: height + + ^self nbCall: #(int XMoveResizeWindow(Display display, self, int x, int y, uint width, uint height)) +]]] + +Now we can select a window and move it. Here we select the second window. +[[[ +aDisplay := NBXLibDisplay open. +aWindow := aDisplay defaultRootWindow managedWindows at: 2. +aWindow x: 10 y: 50 width: 200 height: 500. +aDisplay close. +]]] + + +!! Reading Window Attributes: Handling window attributes +Up to now we did not present how we can handle more complex structures. Here is an example to illustrate it. +To get actual position and size of a Window, we can use the function ==XGetWindowAttributes()== defined as follow: + +[[[ +Status XGetWindowAttributes(Display* display, Window w, XWindowAttributes* window_attributes_return) +]]] + +Like the previous example, ==XGetWindowAttributes== has an output argument ==window_attributes_return==. +In this case, ==XWindowAttributes== is a structure defined like this: + +[[[ +typedef struct { + int x, y; /* location of window */ + int width, height; /* width and height of window */ + int border_width; /* border width of window */ + int depth; /* depth of window */ + Visual *visual; /* the associated visual structure */ + Window root; /* root of screen containing window */ + int c_class; /* InputOutput, InputOnly*/ + int bit_gravity; /* one of bit gravity values */ + int win_gravity; /* one of the window gravity values */ + int backing_store; /* NotUseful, WhenMapped, Always */ + unsigned long backing_planes;/* planes to be preserved if possible */ + unsigned long backing_pixel;/* value to be used when restoring planes */ + Bool save_under; /* boolean, should bits under be saved? */ + Colormap colormap; /* color map to be associated with window */ + Bool map_installed; /* boolean, is color map currently installed*/ + int map_state; /* IsUnmapped, IsUnviewable, IsViewable */ + long all_event_masks; /* set of events all people have interest in*/ + long your_event_mask; /* my event mask */ + long do_not_propagate_mask; /* set of events that should not propagate */ + Bool override_redirect; /* boolean value for override-redirect */ + Screen *screen; /* back pointer to correct screen */ +} XWindowAttributes; +]]] + +We need a way to define structures and manipulated their fields in the Pharo side and this is what we will see now. + + +!!! Handling C-Structure with NBExternalStructure + +So far we did not define mappings to C structures in NativeBoost but we used ==NBExternalObject== (wrapper to an handle to external opaque objects). +Now we will use NativeBoost to define a structure. Here is the way to proceed: +First we create a subclass of ==NBExternalStructure== and we will add on the class side a description of all the structure fields +using NativeBoost types and aliases. + +!!!! Defining a subclass of ==NBExternalStructure==. + +First we have to create a subclass of ==NBExternalStructure== that will hold this data: +[[[ +NBExternalStructure subclass: #NBXLibXWindowAttributes + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: 'NBXLibTypes' + category: 'X11' +]]] + +Note that the structure uses the shared pool ==NBXLibTypes== to access to the type aliases we already defined. +Before adding the description of all the fields to ==NBXLibXWindowAttributes==, we should define some types that +are needed such as ==Visual==, ==Screen==, ==Colormap==. + +We can either use subclasses of ==NBExternalObject==, but as we don't need them we can just add them +to the shared pool as ==ulong== (pointers - XLib uses the name ==XID==). + +[[[ +NBXLibTypes class>>initialize + Display := #NBXLibDisplay. + Atom := #ulong. + Window := #NBXLibWindow. + AnyPropertyType := 0. + XID := #ulong. + Colormap := XID. + Visual := XID. + Screen := XID. + Bool := #int. + Status := #int. + XWindowAttributes := #NBXLibXWindowAttributes. +]]] + +Note we also define ==Bool== and ==Status== as aliases of ==int==, ==XWindowAttributes== as +an alias of ==#NBXLibXWindowAttributes==. Do not forget to execute ==NBXLibTypes initialize==. + + +!!! Describing the fields + +Now we describe the fields in the ==NBXLibXWindowAttributes== class as follows. + +[[[ +NBXLibXWindowAttributes class>>fieldsDesc + ^ #(int x; + int y; " location of window " + int width; + int height; " width and height of window " + int border_width; " border width of window " + int depth; " depth of window " + Visual visual; " the associated visual structure " + Window root; " root of screen containing window " + int c_class; " InputOutput, InputOnly" + int bit_gravity; " one of bit gravity values " + int win_gravity; " one of the window gravity values " + int backing_store; " NotUseful, WhenMapped, Always " + ulong backing_planes; " planes to be preserved if possible " + ulong backing_pixel; " value to be used when restoring planes " + Bool save_under; " boolean, should bits under be saved? " + Colormap colormap; " color map to be associated with window " + Bool map_installed; " boolean, is color map currently installed" + int map_state; " IsUnmapped, IsUnviewable, IsViewable " + long all_event_masks; " set of events all people have interest in" + long your_event_mask; " my event mask " + long do_not_propagate_mask; " set of events that should not propagate " + Bool override_redirect; " boolean value for override-redirect " + Screen *screen; " back pointer to correct screen " + ) +]]] + +!!!! Initialize accessors. +NativeBoost can also generate all accessors for us with ==NBXLibXWindowAttributes initializeAccessors==. + + +!!!!Defining the new primitive +Now we are ready to define the primitive for ==XGetWindowAttributes()== in the class ==NBXLibWindow== as follows: +[[[ +NBXLibWindow>>primGetAttributesInto: attributes + + ^self nbCall: #(Status XGetWindowAttributes(Display display, self, XWindowAttributes * attributes) ) +]]] + +We define also some methods. +[[[ +NBXLibWindow>>attributes + ^ NBXLibXWindowAttributes window: self. + +NBXLibXWindowAttributes class>>window: aWindow + | attributes | + attributes := self new. + aWindow primGetAttributesInto: attributes. + ^ attributes +]]] + +Now we can read the size of our desktop! Try to print this expression: +[[[ +NBXLibDisplay open defaultRootWindow attributes width +]]] + + +!! Conclusion +In this Chapter we covered a large part of the way we can interact with C libraries using NativeBoost. +What you saw is that we can incrementally and without having to code in C build a bridge. +In addition to automatic marshalling, NativeBoost supports opaque objects via ==NBExternalReference==, +output parameters using ==NBExternalTypeValue== and ==NBExternalArray== and structure using ==NBExternalStructure==. + +Once all the system is setup for Pharo and NativeBoost to load the library —and a lot of things can go wrong with this part— +defining your bindings should be straightforward. A major challenge is to define a nice object-oriented API +around a C library so you can cut the number of parameters to pass to your primitives. diff --git a/NativeBoostX11/figures/displayInstance.pdf b/NativeBoostX11/figures/displayInstance.pdf new file mode 100644 index 0000000000000000000000000000000000000000..51d8ea7526f0445c7962e4525e328ccce990deaf GIT binary patch literal 16517 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 a%PO6m0TcT3;#j#@IC)X2s3eu7Q2!6IFQ#7r literal 0 HcmV?d00001 diff --git a/NativeBoostX11/figures/fourWindows.pdf b/NativeBoostX11/figures/fourWindows.pdf new file mode 100644 index 0000000000000000000000000000000000000000..961eb96c14a6f5e8c2b61fae6cbb822197435291 GIT binary patch literal 19757 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
  • _T@raBj|!Ks$V+Nzdh!6SCmI05rQI> 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 literal 0 HcmV?d00001 diff --git a/pillar.conf b/pillar.conf index d2bf6d0..5aaea66 100644 --- a/pillar.conf +++ b/pillar.conf @@ -31,6 +31,7 @@ "Zinc-REST/Zinc-REST.pillar", "PillarChap/Pillar.pillar", "Artefact/Artefact.pillar", + "NativeBoostX11/NativeBoostX11.pillar", "STON/STON.pillar" ] } diff --git a/support/templates/book.latex.template b/support/templates/book.latex.template index a806d23..a959176 100644 --- a/support/templates/book.latex.template +++ b/support/templates/book.latex.template @@ -20,6 +20,8 @@ {../Zinc-HTTP/} {../Zinc-Encoding-Meta/} {../Zinc-REST/} + {../NativeBoostX11/} + {../Fuel/} {../STON/} } %=================================================================