On 15 November 2017 at 20:47, Esteban Lorenzano <esteba...@gmail.com> wrote:
>
> which could be implemented...
>    FFIExternalType class >> newBuffer.
>         ^ByteArray new: (self externalTypeSize)
>
> testGetPageSizeByIndex
>         | document page_index widthBuffer heightBuffer width height result|
>         PDFium FPDF_InitLibrary.
>         document := PDFium FPDF_LoadDocument__file_path:  helloPdf
> password: ''.
>         widthBuffer := FFIFloat64 buffer.
>         heightBuffer := FFIFloat64 buffer.
>         page_index := 0. "Its zero based"
>         result := PDFium FPDF_GetPageSizeByIndex__document: document
>                          page_index: 0
>                          width: widthBuffer
>                          height: heightBuffer.
>         width := widthBuffer doubleAt: 1.
>         height := heightBuffer doubleAt: 1.

I'm about to do something similar with for this prototype...
void clang_getFileLocation(
             CXSourceLocation location,
             CXFile *file,
             unsigned *line,
             unsigned *column,
             unsigned *offset);

Now 'uints' are good to work with since they are consistently 4 bytes
on all modern platforms
(Windows / Linux / Unix) x (32bit / 64bit)
http://nickdesaulniers.github.io/blog/2016/05/30/data-models-and-word-size/

So I using this FFI definition...
    Libclang >> clang_getFileLocation__location: location file: file
line: line column: column offset: offset
        self ffiCall: #(void clang_getFileLocation(
                CXSourceLocation location,
                CXFile *file,
                uint *line,
                uint *column,
                uint *offset))

with this application code...
    lineBuffer := FFIUInt32 newBuffer.
    columnBuffer := FFIUInt32 newBuffer.
    offsetBuffer := FFIUInt32 newBuffer.
    Libclang clang_getFileLocation__location: cxLocation
            file: cxFile
            line: lineBuffer
            column: columnBuffer
            offset: offsetBuffer.

but to unwrap the buffer the following is not available...
     line := lineBuffer uint32At: 1.

Other candidates are senders of #integerAt:size:signed:
from which the only one dealing in 4 bytes is...
    ByteArray >> unsignedLongAt: byteOffset
          ^self integerAt: byteOffset size: 4 signed: false

which (apart from 'ulong' being semantically different from the
original 'uint' C definition)
seems a poor cross-platform choice, since 'long' is the only integer
type whose size that varies between 32-bit & 64-bit.
* 
https://software.intel.com/en-us/articles/size-of-long-integer-type-on-different-architecture-and-os

There is ByteArray >> platformUnsignedLongAt:
but again the original C declaration was an uint, so it still feels
wrong to use 'long' converter.

The remaining option is directly using the lower level api, but its a
bit ugly...
    lineBuffer := FFIUInt32 newBuffer.
    columnBuffer := FFIUInt32 newBuffer.
    offsetBuffer := FFIUInt32 newBuffer.
    Libclang clang_getFileLocation__location: cxLocation
            file: cxFile
            line: lineBuffer
            column: columnBuffer
            offset: offsetBuffer.
    line := lineBuffer integerAt: 1 size: 4 signed: false.
    column := columnBuffer integerAt: 1 size: 4 signed: false.
    offset := offsetBuffer integerAt: 1 size: 4 signed: false.
    ^{ line . column. offset }

So are additional type converters required for ByteArray?

Or alternatively, could FFIExternalType get an extra ByteArray instance variable
that is usually nil, but is available when we want to deal concretely
with an external type
while keeping the type info associated, rather needing a raw ByteArray.
For example...

Object subclass: #FFIExternalType
    instanceVariableNames: 'pointerArity loader buffer'
    classVariableNames: ''
    package: 'UnifiedFFI-Types'

FFIExternalType >> buffer
     ^ buffer ifNil: [ buffer := ByteArray new: (self externalTypeSize) ].
        buffer pin.

FFIExternalType >> dereference
    ^ self basicHandle: self buffer at: 1

then presumably I could do "something" like...

    line := FFIUInt32 new.
    column := FFIUInt32 new.
    offset := FFIUInt32 new.
    Libclang clang_getFileLocation__location: cxLocation
            file: cxFile
            line: line buffer
            column: column buffer
            offset: offset buffer.
    ^ { line value . column value . offset value}

or maybe #bufferPointer would be better than #buffer

I'm experimenting along this line, but I'm currently breaking my Image
so I pause to seek feedback on the idea.

cheers -ben

Reply via email to