[squeak-dev] FFI (Plugin) | Question about multi-dimensional arrays (e.g., char**, int**, void*****...)

Marcel Taeumel marcel.taeumel at hpi.de
Mon Jun 15 13:38:58 UTC 2020


> BTW: "char *libs[n]" doesn't work and won't compile ;)

Hmm... what could the FFI Call spec look like for:

static size_t _sqo_lib_paths(size_t const n, char (*libs[n]))


Maybe like this:

cdeclSqoLibPaths: n with: libs
    <cdecl: size_t '_sqo_lib_paths' (size_t char**)>

Well, calling "self cdeclSqoLibPaths: 0 with: nil" would return the required size n for libs. Then you could construct a byte array with "n * ExternalType size_t byteSize" bytes so that the library can store all the pointers...

n := self cdeclSqoLibPaths: 0 with: nil.
libs := ByteArray new: n * ExternalType size_t byteSize.
self cdeclSqoLibPaths: n with: libs.

Should work. Alternatively, you can use external memory, not Squeak's object memory:

n := self cdeclSqoLibPaths: 0 with: nil.
libs := ExternalAddress allocate: n * ExternalType size_t byteSize.
self cdeclSqoLibPaths: n with: libs.

In both cases, you would need to put it into an object to start reading the data. For example, an ExternalData ... or a fitting ExternalTypeAlias:

data := ExternalData fromHandle: libs type: ExternalType void asPointerType.

Now it get's tricky. At the moment, we cannot tell ExternalData about the "char**" type. So, "data size: n; do: [:each | ... ]" will not work. We can, however, do it manually:

strings := (1 to: n) collect: [:index |
   | data |
   data := libs pointerAt: (index-1 * ExternalAddress wordSize)+1.
   data := ExternalData fromHandle: data type: ExternalType string "char*".
   data fromCString].

libs class == ExternalAddress ifTrue: [libs free].


But then we have to watch out for the pointer sizes on our own.

Maybe we can help here to improve the workflow and avoid redundant code.

Best,
Marcel
Am 15.06.2020 15:00:58 schrieb Tobias Pape <das.linux at gmx.de>:

> On 15.06.2020, at 14:52, Marcel Taeumel wrote:
>
> > Hello, C99:
>
> So, "char (*libs[n])" would be equivalent to "char *libs[n]", which is an array of n pointers, each pointing to a character ... which is a null-terminated string, I suppose? Like "char **argv" or "char *argv[]" ... but with n

It is an array of n char-pointers (in fact, C-Strings), and n refers to an earlier variable in the parameter list...

BTW: "char *libs[n]" doesn't work and won't compile ;)
-t

>
> Best,
> Marcel
>> Am 15.06.2020 14:34:02 schrieb Tobias Pape :
>>
>>
>> > On 15.06.2020, at 14:24, Jakob Reschke wrote:
>> >
>> >
>> > Marcel Taeumel schrieb am Mo., 15. Juni 2020, 13:22:
>> >
>> > - Accept type names such as "int **" or "int[][]" in FFI-call specs and struct-field spec
>> >
>> > One further note: int[][] is not valid C in parameter types. Only the first [] can be without length, and is equivalent to a pointer. So char*argv[] is the same as char**argv. Valid parameter type examples: int a[][3], int b[][2][3]. These are like int(*a)[3] and int(*b)[2][3] if I am not mistaken.
>> >
>>
>> Hello, C99:
>>
>> /* Find all paths that may contain dynamic libraries.
>> * Returns their count. libs may be NULL to get allocation size
>> */
>> static size_t _sqo_lib_paths(size_t const n, char (*libs[n]))
>> {
>> /*...*/
>> }
>>
>> ;)
>>
>> -t
>>
>



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20200615/a8b97375/attachment.html>


More information about the Squeak-dev mailing list