Search code examples
smalltalkvisualworks

How to get the value of a CPointer in Visual Works


The following C function populate a C struct in Visual Works (is working ok):

<C:int ssh_pki_import_pubkey_file (const char * filename,  VOID * pkey)>

Now a second function is defined as:

int ssh_userauth_try_publickey (ssh_session session, const char * username, const ssh_key pubkey)

In Smalltalk:

<C:int ssh_userauth_try_publickey (VOID session, const char * username, const VOID pubkey)>

If i call the second function (ssh_userauth_try_publickey) with the populated argument (with no transformation) of the first function (ssh_pki_import_pubkey_file) it fail.

So VOID * pkey has to match const VOID pubkey.

In GemStone/S this is done with #'&ptr' and #'ptr', so #'&ptr' will get the value of the pointer (the CPointer’s value will be passed and updated on return).

Reading DLL & C Connect User’s Guide does not yield result yet.


Solution

  • Short answer

    use void** in your first function and void* in your second function

    Long answer

    In C, void means "nothing" and if you have a return type of void that means you don't return anything. But void* means pointer to nothing (...that i know about)... basically you get a pointer to something where you don't know what it is. But it's still a pointer, which is not nothing.

    If you have a function that produces a value not via return but via parameter, you need to pass a pointer so that the function can set its value. You can do that via void* but that's unintentional. Consider the following wrong C code:

    void var;
    myFunc(&var);
    

    myFunc would take a void* as parameter in order to fill its value, but a variable of type void is wrong because what would be its value. In correct C you would do it like that:

    void* var = NULL;
    myFunc(&var);
    

    Here the type of var is clearly a pointer and its value is even initialised. For myFunc there's no real difference here, except that it'll now have a void** as parameter.

    So if you modify ssh_pki_import_pubkey_file's declaration to have a void** parameter and change ssh_userauth_try_publickey's declaration to accept a void* parameter, you should be fine.