Eliot Miranda a écrit :
On Mon, Sep 22, 2008 at 6:19 AM, Igor Stasenko <siguctua@gmail.com mailto:siguctua@gmail.com> wrote:
2008/9/22 Gerardo Richarte <gera@corest.com <mailto:gera@corest.com>>: > Igor Stasenko wrote: >> 2008/9/22 Gerardo Richarte <gera@corest.com <mailto:gera@corest.com>>: >> >>> There's a native function I need to call (I called it 'aPrintf' in >>> the code below) with a specific calling convention: >>> >> I wondering , why you prefer using string formatting in C, while in >> smalltalk you have own? You can easily format strings in smalltalk, >> and print only the resulting string w/o need in inventing safe schemes >> or conversion. >> > Hi Igor, nice to see you again! > > I knew this was going to happen :) > > It was just an example, I'm not using string formatting. The actual > function I'm calling is the callout interface for OpenFirmware, through > which OpenFirmware provides services to the booted operating > system. Pretty much like BIOS' INT mechanism, but much more > powerful. > Okay. Then i don't see any problems with this primitive, except maybe one thing: a primitive should never change the contents of any argument(s). As in general smalltalk methods, a primitive should be allowed to change the contents only of receiver object, otherwise its breaking a smalltalk encapsulation rules. I would advice you to allocate separate byte array and fill it with values, then pass to C routine. Since its a byte array you don't need to care about it contents, and don't need a cleanup (GC will collect it as garbage eventually).
No need to use a Smalltalk object to hold the copy. Just use alloca (stack allocating version of malloc).
But this is the kind of thing an FFI does during marshalling anyway. Gerardo, why can't you use the FFI?
He said arguments type was not fixed, but would depend on service requested in first argument as I understand it.
So the same function has different interfaces. Would you suggest the solution is as simple as declaring the same function with several interfaces?
like:
withFormat: aString printInteger: anInteger <cdecl: void 'myprintf'( char * long )> ^self externalCallFailed
withFormat: aString printDouble: aDouble <cdecl: void 'myprintf'( char * double )> ^self externalCallFailed
printInteger: anInteger ^self withFormat: '%d' print: anInteger
printDouble: aDouble ^self withFormat: '%f' print: anInteger
Nicolas