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