in reply to Calling a function form an external DLL with Inline::C on windows

Hi,

As regards Inline::C, you have:
use strict; use warnings; use Inline C => Config => MYEXTLIB => 'd:\path\to\CrappyLibrary.dll', INC => '-Id:\path\to', BUILD_NOISY => 1; use Inline C => 'DATA'; my $result = RegisterClient2($client_id, $S{read_IP}); __DATA__ __C__ #include "Easy4ApiDef.h"
I think you've *nearly* nailed it. To make it work you could probably invoke the help of the 'autowrap' config option ... see the Inline::C docs (I'm not really up to speed with this aspect of Inline::C).

Instead, I would probably do the wrapping myself. Something like:
use strict; use warnings; use Inline C => Config => MYEXTLIB => 'd:\path\to\CrappyLibrary.dll', INC => '-Id:\path\to', BUILD_NOISY => 1; use Inline C => 'DATA'; my $client_id = 5; #numeric my $read_IP = 'whatever'; #string my $result = wrap_RegisterClient2($client_id, $S{read_IP}); __DATA__ __C__ #include "Easy4ApiDef.h" int wrap_RegisterClient2(int cl_id, char* read_ip) { return RegisterClient2(cl_id, read_ip); }
This should work ok with the gcc compiler (no hope at all with M$ compilers, as they can't link to dll's).

Update: And now ... let's check out yesterday's news ...

Cheers,
Rob

Replies are listed 'Best First'.
Re^2: Calling a function form an external DLL with Inline::C on windows
by Anonymous Monk on Aug 06, 2010 at 11:46 UTC
    Thanks to the help from BrowserUK, I've already figured out that I have to write wrapper functions.

    I've tried it the way you did above:

    int wrap_RegisterClient2(int cl_id, char* read_ip) { return RegisterClient2(cl_id, read_ip); }

    but it doesn't work, I get the same error message as in the case without the wrapper.

    It works with BrowserUK's method. In fact, I have to go one step further:

    int wRegisterClient2( SV *id, SV *IP ) { int c_id = SvIV( id ); char *c_ip = SvPVX( IP ); int result = RegisterClient2( &c_id, c_ip ); printf("%d", c_id); sv_setiv(id, (IV) c_id); return result; }

    Basically, the purpose of this RegisterClient2 function is to establish contact with the instrument that listens on the given IP address, and it gives back a unique numeric id in nClientId that I have to use in further calls. And if I want to access this id from Perl, I have to write back the integer value into the SV that was passed to the wrapper.

    So what follows now is me rolling up my sleeves and go elbow-deep into perlguts.

    Thanks to the advice anyway.
      I've tried it the way you did above:
      int wrap_RegisterClient2(int cl_id, char* read_ip) { return RegisterClient2(cl_id, read_ip); }
      but it doesn't work, I get the same error message as in the case without the wrapper.

      The problem, I believe, is that unless all the parameters, and the return type, are types that the default typemap knows how to handle, Inline::C doesn't wrap and export it. And it appears that the default typemap doesn't know how to handle int *.

      So, whilst this works fine:

      #! perl -slw use strict; #use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => '_test', CLEAN_AFTER_BUILD => 0; int test( int i ) { return i; } END_C print test( 123 ); __END__ C:\test>test 123

      This doesn't:

      #! perl -slw use strict; #use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => '_test', CLEAN_AFTER_BUILD => 0; int test( int *i ) { return *i; } END_C print test( 123 ); __END__ C:\test>test Warning. No Inline C functions bound to Perl in C:\test\test.pl Check your C function definition(s) for Inline compatibility Use of inherited AUTOLOAD for non-method main::test() is deprecated at + C:\test\test.pl line 12. Can't locate auto/main/test.al in @INC (@INC contains: C:\test\_Inline +\lib C:/Perl64/site/lib C:/Perl64/lib .) at C:\test\test.pl line 12

      There is the TYPEMAPS configuration option, but I haven't seen any (good) documentation on that. And finding the default typemap and looking at that doesn't yield many clues.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        Seems like a correct diagnosis.

        However, it is possible to work around this issue by declaring all parameters of the wrapper functions as SV*, then manipulating their contents inside - just as you've showed it.

        Now I've written all these wrapper functions, and consequently I'm able to get data from the instrument.

        All that's left is to integrate it with the existing robot movement and EUT-driver code. I hope I won't run into any further issues with timing, serial comms, windows dark magic, etc.
      I've already figured out that I have to write wrapper functions.

      Yes, the reference (in the update) to "yesterday's news" was meant to be acknowlegement of the fact that the isssue had already been resolved :-)

      Cheers,
      Rob