http://www.perlmonks.org?node_id=134941

mikfire has asked for the wisdom of the Perl Monks concerning the following question:

I have posted this question to the inline mailing list, but haven't seen any response. I thought I would try my fellow monks to see if they could offer a clue.

I have been playing with Inline::C, trying to wrap an API so I could access it via perl. I have read the docs for Inline::C and explored the cookbook enough to figure out what I needed to do. I have been also able to get the examples contained within the cookbook working.

I wrote my code and, after getting rid of several stupid typos ( I am still trying to convince my fingers to stop adding a "$" in front of variable names :), the code compiled but returned an error. I worked at it for a little while and then decided to extract the C code, write a simple main() and see what happened.

It compiled, ran and returned without the error.

I am now very confused. I am dead certain I have missed something very silly - this is the first time I have tried to use Inline and my three previous attempts at using XS all failed

This is the code:

#!/usr/local/bin/perl -w use strict; use Inline C => Config => LIBS => "-lpdadminapi", PREFIX => 'my_', INC => "-I/usr/include/PolicyDirector"; use Inline C => << 'END_C'; #include <ivadminapi.h> /* So named in case there is some conflict of which I am unaware */ int my_create_context( char* user, char* passwd ) { ivadmin_context ctx; ivadmin_response rsp; unsigned long status; int i; printf("Establising context as %s (%s)\n", user, passwd ); /* This is the call that is failing */ status = ivadmin_context_createdefault(user,passwd,&ctx,&rsp); if ( ivadmin_response_getok(rsp) ) { printf("ivadmin_context_createdefault succeeded\n" ); } else { for(i=0; i<ivadmin_response_getcount(rsp);i++) { printf( "ivadmin_context_createdefault : (%d) %s\n", ivadmin_response_getcode( rsp, i ), ivadmin_response_getmessage( rsp, i ) ); } } ivadmin_free( rsp ); return status; } END_C my ( $foo, $user, $passwd ); $user = 'xxxxxxxx'; $passwd = 'xxxxxxxx'; $foo = create_context( $user, $passwd ); print "status = $foo\n";
And this is the main() I wrote to test the C code directly:
int main() { int stat; stat = create_context("xxxxxxxx", "xxxxxxxx" ); printf( "Stat = %d\n", stat ); return 0; }
If anybody could give me a pointer, I would appreciate it to no end. Again, I am quite certain this is my mistake but I really have no idea how to approach it.

Thanks,
mikfire

Replies are listed 'Best First'.
(Ovid) Re: Inline::C code doesn't work, but the C code does
by Ovid (Cardinal) on Dec 28, 2001 at 23:39 UTC

    I saw your question on the mailing list and it was bugging me that no one bothered to answer it. Of course, since I've joined the mailing list, your's is the only post that I've seen :(

    On the mailing list code, you're not having a problem. With this code, you've calling a sub you haven't declared :) - my_create_context versus create_context. Of course, since it's obvious you're still massaging it, this is not the problem. From what you are saying, the problem lies here:

    /* This is the call that is failing */ status = ivadmin_context_createdefault(user,passwd,&ctx,&rsp);

    How do you know this is where the error is? You don't supply us with any error message. Also, and I know this sounds too elementary, have you printed all of the values before and after the "createdefault" call?

    (Entering deep waters here) I'm also wondering about the typedefs for ivadmin_context and ivadmin_response. Do you need to specify new typemaps for them? I thought this was only an issue when declaring return types, but I could be wrong. Do you have anyway of verifying that Perl is handling these correctly?

    Cheers,
    Ovid

    Update: You mentioned on the mailing list that you're using the same compiler as when you compiled Perl. Are you using the same 'make' utility? An article at http://www.perl.com/ by the Inline author suggests that this will cause problems (though he does not elaborate).

    I'd also try the following one-liner:

    perl -MInline=Info,force,NoClean yourcode.pl

    That forces Information about bound subs to be printed to STDERR. It also forces a recompile and leaves the build directories intact so you can browse through them for more information.

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      I know the call to ivadmin_context_createdefault() isn't working because ivadmin_response_getok is saying so. And, since the identical code works as a C program, I know it isn't my call to the library.

      The PREFIX option on the use Inline C line causes perl to "strip" that prefix from the function as defined in the C code. Thus, I define it as my_create_context in the C code, and use it as create_context in the perl code.

      Upon reading the docs a bit closer, if Inline didn't like the return type from my_context_create, it would simply ignore the function. As I can call it from perl, I assume this isn't the problem. Again, if I read the docs right, I don't need a typemap unless I intend on using one of those structs as a return type.

      I tried your suggestion on the update, and it is saying the function has been bound to perl. I have also browsed the generated XS code and it looks correct to me, although I think I indicated previously that my XS skills are nonexistent.

      I am using the same make.

      Thanks for the suggestions, Ovid. I am back to hitting the docs and trying ( once again ) to work my way through perlapi.

      mikfire