: Passing array to C func() expecting argv 
Author Message
 : Passing array to C func() expecting argv

There's a function in a shared library that's expecting an array of pointers.
Basically, it's wanting 'argv' as in:

main(int argc, char **argv)

Anyway, in my Smalltalk code (attached) the procedure (isdConnect) is defined
as accepting as its only argument, a char **, and I pass it #('arg1' 'arg2'
'arg3' 'arg4') but it complains with an exception:

'Unhandled exception: Invalid procedure argument.'
CPointerType>>coerceForArgument:
CProcedureType>>call:from:withArguments:
ExternalProcedure>>callFrom:withArguments:
[] in IsdIO>>isdConnect:
ExternalAccessFailed class(GenericException class)>>handle:do:
IsdIO>>isdConnect:
IsdEcho(IsdWorker)>>connect:
IsdEcho(IsdWorker)>>startWith:
IsdEcho class>>unboundMethod

Is this allowed, or is there another way to pass these?
--
Open Source middleware available at http://www.*-*-*.com/ ~tgagne/

[ Isect.st 5K ]
ExternalInterface subclass: #IsdIO
        includeFiles: ''
        includeDirectories: ''
        libraryFiles: 'libisdio.so '
        libraryDirectories: '/usr/local/lib '
        generateMethods: ''
        beVirtual: false
        optimizationLevel: #debug
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: 'IsdIODictionary '
        category: 'Isect'!

!IsdIO methodsFor: 'types'!

int16_t
        <C: typedef void * int16_t>!

int32_t
        <C: typedef void * int32_t>!

int64_t
        <C: typedef void * int64_t>!

isdHeader
        <C: typedef struct  {
                        int32_t len, sequence;
                        int16_t reply, error, command, version;
                        u_int32_t workerid;
                        int16_t more;
                        int16_t unused[17];
                        int64_t aligner;
                } isdHeader>!

u_int32_t
        <C: typedef void * u_int32_t>! !

!IsdIO methodsFor: 'procedures'!

isdConnect: arg1
        <C: int isdConnect(char * * arg1)>
        ^self externalAccessFailedWith: _errorCode!

isdEcho: arg1
        <C: char *  isdEcho(const char * arg1)>
        ^self externalAccessFailedWith: _errorCode!

isdInit
        <C: void isdInit(void)>
        ^self externalAccessFailedWith: _errorCode!

isdLogin
        ^self isdLogin:'isectd'!

isdLogin: arg1
        ^self isdLogin:arg1 with: 'op'!

isdLogin: arg1 with: arg2
        ^self isdLogin:arg1 with: arg2 with:2!

isdLogin: arg1 with: arg2 with: arg3
        <C: int isdLogin(char * arg1, char * arg2, int arg3)>
        ^self externalAccessFailedWith: _errorCode!

isdLogout: arg1
        <C: void isdLogout(int arg1)>
        ^self externalAccessFailedWith: _errorCode!

isdRecv: arg1
        | header |

        header := self isdHeader gcMalloc.
        header memberAt:#more put:1.
        ^self isdRecv:arg1 with:header.!

isdRecv: arg1 with: arg2
        <C: char *  isdRecv(int arg1, isdHeader * arg2)>
        ^self externalAccessFailedWith: _errorCode!

isdSend: arg1 with: arg2
        ^self isdSend:arg1 with:arg2 with:-1.!

isdSend: arg1 with: arg2 with: arg3
        | header  |

        header := self isdHeader gcMalloc.
        header memberAt:#more put:1.
        ^self isdSend:arg1 with:arg2 with:-1 with:header.!

isdSend: arg1 with: arg2 with: arg3 with: arg4
        <C: int isdSend(int arg1, char * arg2, int arg3, isdHeader * arg4)>
        ^self externalAccessFailedWith: _errorCode! !

!IsdIO methodsFor: 'defines'!

ISDARGHOST
        <C: #define ISDARGHOST 1
        >!

ISDARGMAX
        <C: #define ISDARGMAX 4
        >!

ISDARGSERVICE
        <C: #define ISDARGSERVICE 2
        >!

ISDARGWID
        <C: #define ISDARGWID 3
        >!

isdHeadlessArgvStart
        ^3!

ISDXSERVICE
        <C: #define ISDXSERVICE "isdexec"
        >! !

!IsdIO methodsFor: 'documentation'!

examples
"
The following code does a quick login/logout.  This is a good test if all you
want to do is debug loading the libraries.

| lib |

lib := IsdIO new.
lib isdInit.

This next test logs in and out quickly without sending any transactions

| lib sock |

lib := IsdIO new.
sock := lib isdLogin.
lib isdLogout:sock.

This next sections tests sending a single transaction to the echo worker.

| lib sock bytes reply |

lib := IsdIO new.
self halt.
sock := lib isdLogin: nil with:'echo'.
bytes := lib isdSend:sock with:'Hello, world!!'.
reply := lib isdRecv:sock.
lib isdLogout:sock.
"! !

Object subclass: #IsdClient
        instanceVariableNames: 'isdLib isdSocket '
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Isect'!

!IsdClient methodsFor: 'behavior'!

login: aHostId service: aServiceId priority: anInteger
        ^self isdSocket: (self isdLib isdLogin:aHostId with:aServiceId with:anInteger).!

logout
        self isdLib isdLogout:(self isdSocket).
        ^self isdSocket: nil.!

recv
        ^self isdLib isdRecv:(self isdSocket).!

send: aByteArray
        ^self isdLib isdSend:(self isdSocket) with: aByteArray with:(aByteArray size).! !

!IsdClient methodsFor: 'initialization'!

finish
        ObjectMemory quit.!

start
        ^self subclassResponsibility!

workLoop
        ^self subclassResponsibility! !

!IsdClient methodsFor: 'accessing'!

isdLib
        isdLib isNil ifTrue:[
                self isdLib:(IsdIO new)].

        ^isdLib.!

isdLib: anIsdIO
        isdLib := anIsdIO.
        ^isdLib.!

isdSocket
        ^isdSocket.!

isdSocket: anInteger
        isdSocket := anInteger.
        ^isdSocket.! !

!IsdClient methodsFor: 'documentation'!

headless
"
To create an headless image, evalute:

        HeadlessImage default saveHeadless: 'isdecho.im'

This image is already modified so that isdClient will be started when the headless
image is started.  In case you're wondering, in HeadlessImage->returnFromSnapshot
I added:
        (IsdClient open) fork.
and comment-out the rest of the startup-script nonesense.
"! !

IsdClient subclass: #IsdWorker
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Isect'!

!IsdWorker methodsFor: 'initialization'!

start
        | argv isdArgv |

        argv := CEnvironment commandLine.
        isdArgv := argv copyFrom: (self isdLib isdHeadlessArgvStart) to: (argv size).

        (isdArgv size >= 4) ifTrue: [
                self startWith: isdArgv.
                self finish.
        ].!

startWith:anArray

                self connect:anArray.
                self workLoop.
                self logout! !

!IsdWorker methodsFor: 'behavior'!

connect
        | argv isdArgv |

        argv := CEnvironment commandLine.
        isdArgv := argv copyFrom: (self isdLib isdHeadlessArgvStart) to: (argv size).
        ^self connect:isdArgv!

connect:anArray

        (anArray size >= (self isdLib ISDARGMAX)) ifTrue: [
                self isdSocket: (self isdLib isdConnect: anArray).
        ].

        ^self isdSocket.! !

IsdWorker subclass: #IsdEcho
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Isect'!

!IsdEcho methodsFor: 'documentation'!

examples
"
Try:

IsdEcho new startWith:#('localhost' '15760' '1' '-secho').

"! !

!IsdEcho methodsFor: 'behavior'!

workLoop
        | message |

        [(message := self recv) isNotNil] whileTrue: [self send: message].! !



Wed, 18 Jun 1902 08:00:00 GMT  
 : Passing array to C func() expecting argv
There's a function in a shared library that's expecting an array of
pointers.
Basically, it's wanting 'argv' as in:

main(int argc, char **argv)

Anyway, in my smalltalk code (attached) the procedure (isdConnect) is
defined
as accepting as its only argument, a char **, and I pass it #('arg1'
'arg2'
'arg3' 'arg4') but it complains with an exception:

'Unhandled exception: Invalid procedure argument.'
CPointerType>>coerceForArgument:
CProcedureType>>call:from:withArguments:
ExternalProcedure>>callFrom:withArguments:
[] in IsdIO>>isdConnect:
ExternalAccessFailed class(GenericException class)>>handle:do:
IsdIO>>isdConnect:
IsdEcho(IsdWorker)>>connect:
IsdEcho(IsdWorker)>>startWith:
IsdEcho class>>unboundMethod

Is this allowed, or is there another way to pass these?
--
Open Source middleware available at http://home.netcom.com/~tgagne/
ExternalInterface subclass: #IsdIO
        includeFiles: ''
        includeDirectories: ''
        libraryFiles: 'libisdio.so '
        libraryDirectories: '/usr/local/lib '
        generateMethods: ''
        beVirtual: false
        optimizationLevel: #debug
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: 'IsdIODictionary '
        category: 'Isect'!

!IsdIO methodsFor: 'types'!

int16_t
        <C: typedef void * int16_t>!

int32_t
        <C: typedef void * int32_t>!

int64_t
        <C: typedef void * int64_t>!

isdHeader
        <C: typedef struct  {
                        int32_t len, sequence;
                        int16_t reply, error, command, version;
                        u_int32_t workerid;
                        int16_t more;
                        int16_t unused[17];
                        int64_t aligner;
                } isdHeader>!

u_int32_t
        <C: typedef void * u_int32_t>! !

!IsdIO methodsFor: 'procedures'!

isdConnect: arg1
        <C: int isdConnect(char * * arg1)>
        ^self externalAccessFailedWith: _errorCode!

isdEcho: arg1
        <C: char *  isdEcho(const char * arg1)>
        ^self externalAccessFailedWith: _errorCode!

isdInit
        <C: void isdInit(void)>
        ^self externalAccessFailedWith: _errorCode!

isdLogin
        ^self isdLogin:'isectd'!

isdLogin: arg1
        ^self isdLogin:arg1 with: 'op'!

isdLogin: arg1 with: arg2
        ^self isdLogin:arg1 with: arg2 with:2!

isdLogin: arg1 with: arg2 with: arg3
        <C: int isdLogin(char * arg1, char * arg2, int arg3)>
        ^self externalAccessFailedWith: _errorCode!

isdLogout: arg1
        <C: void isdLogout(int arg1)>
        ^self externalAccessFailedWith: _errorCode!

isdRecv: arg1
        | header |

        header := self isdHeader gcMalloc.
        header memberAt:#more put:1.
        ^self isdRecv:arg1 with:header.!

isdRecv: arg1 with: arg2
        <C: char *  isdRecv(int arg1, isdHeader * arg2)>
        ^self externalAccessFailedWith: _errorCode!

isdSend: arg1 with: arg2
        ^self isdSend:arg1 with:arg2 with:-1.!

isdSend: arg1 with: arg2 with: arg3
        | header  |

        header := self isdHeader gcMalloc.
        header memberAt:#more put:1.
        ^self isdSend:arg1 with:arg2 with:-1 with:header.!

isdSend: arg1 with: arg2 with: arg3 with: arg4
        <C: int isdSend(int arg1, char * arg2, int arg3, isdHeader * arg4)>
        ^self externalAccessFailedWith: _errorCode! !

!IsdIO methodsFor: 'defines'!

ISDARGHOST
        <C: #define ISDARGHOST 1
        >!

ISDARGMAX
        <C: #define ISDARGMAX 4
        >!

ISDARGSERVICE
        <C: #define ISDARGSERVICE 2
        >!

ISDARGWID
        <C: #define ISDARGWID 3
        >!

isdHeadlessArgvStart
        ^3!

ISDXSERVICE
        <C: #define ISDXSERVICE "isdexec"
        >! !

!IsdIO methodsFor: 'documentation'!

examples
"
The following code does a quick login/logout.  This is a good test if
all you
want to do is debug loading the libraries.

| lib |

lib := IsdIO new.
lib isdInit.

This next test logs in and out quickly without sending any transactions

| lib sock |

lib := IsdIO new.
sock := lib isdLogin.
lib isdLogout:sock.

This next sections tests sending a single transaction to the echo
worker.

| lib sock bytes reply |

lib := IsdIO new.
self halt.
sock := lib isdLogin: nil with:'echo'.
bytes := lib isdSend:sock with:'Hello, world!!'.
reply := lib isdRecv:sock.
lib isdLogout:sock.
"! !

Object subclass: #IsdClient
        instanceVariableNames: 'isdLib isdSocket '
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Isect'!

!IsdClient methodsFor: 'behavior'!

login: aHostId service: aServiceId priority: anInteger
        ^self isdSocket: (self isdLib isdLogin:aHostId with:aServiceId
with:anInteger).!

logout
        self isdLib isdLogout:(self isdSocket).
        ^self isdSocket: nil.!

recv
        ^self isdLib isdRecv:(self isdSocket).!

send: aByteArray
        ^self isdLib isdSend:(self isdSocket) with: aByteArray
with:(aByteArray size).! !

!IsdClient methodsFor: 'initialization'!

finish
        ObjectMemory quit.!

start
        ^self subclassResponsibility!

workLoop
        ^self subclassResponsibility! !

!IsdClient methodsFor: 'accessing'!

isdLib
        isdLib isNil ifTrue:[
                self isdLib:(IsdIO new)].

        ^isdLib.!

isdLib: anIsdIO
        isdLib := anIsdIO.
        ^isdLib.!

isdSocket
        ^isdSocket.!

isdSocket: anInteger
        isdSocket := anInteger.
        ^isdSocket.! !

!IsdClient methodsFor: 'documentation'!

headless
"
To create an headless image, evalute:

        HeadlessImage default saveHeadless: 'isdecho.im'

This image is already modified so that isdClient will be started when
the headless
image is started.  In case you're wondering, in
HeadlessImage->returnFromSnapshot
I added:
        (IsdClient open) fork.
and comment-out the rest of the startup-script nonesense.
"! !

IsdClient subclass: #IsdWorker
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Isect'!

!IsdWorker methodsFor: 'initialization'!

start
        | argv isdArgv |

        argv := CEnvironment commandLine.
        isdArgv := argv copyFrom: (self isdLib isdHeadlessArgvStart) to: (argv
size).

        (isdArgv size >= 4) ifTrue: [
                self startWith: isdArgv.
                self finish.
        ].!

startWith:anArray

                self connect:anArray.
                self workLoop.
                self logout! !

!IsdWorker methodsFor: 'behavior'!

connect
        | argv isdArgv |

        argv := CEnvironment commandLine.
        isdArgv := argv copyFrom: (self isdLib isdHeadlessArgvStart) to: (argv
size).
        ^self connect:isdArgv!

connect:anArray

        (anArray size >= (self isdLib ISDARGMAX)) ifTrue: [
                self isdSocket: (self isdLib isdConnect: anArray).
        ].

        ^self isdSocket.! !

IsdWorker subclass: #IsdEcho
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Isect'!

!IsdEcho methodsFor: 'documentation'!

examples
"
Try:

IsdEcho new startWith:#('localhost' '15760' '1' '-secho').

"! !

!IsdEcho methodsFor: 'behavior'!

workLoop
        | message |

        [(message := self recv) isNotNil] whileTrue: [self send: message].! !



Wed, 18 Jun 1902 08:00:00 GMT  
 
 [ 2 post ] 

 Relevant Pages 

1. Passing variables from Func to Func

2. QUESTION: Passing variables from Func to Func???

3. pass values in stack to func...

4. Passing dict-type arg list to 2nd func??

5. Passing Named Paramater To A C Func?

6. passing argv. to a program

7. How to pass the argv variables from batch file to .tcl file

8. How to pass the argv variables from batch file to .tcl file

9. TCL Shell on the Mac to pass argc and argv

10. Expect "lrange $argv 0 0"

11. Wishx interpreter damages argv array

12. Can't pass boolean array into Array Subset in a For loop

 

 
Powered by phpBB® Forum Software