4

I have two libraries, I want to call routines in the first library, they then call routines in the second library, but crash because those symbols are undefined. Is it possible to say "load these symbols" from library XX even though I don't want to call them?

testlib1.c:

#include <stdio.h>
void sub2();
void sub1() {
  printf("Called sub1\n");
  sub2();
}

testlib2.c:

#include <stdio.h>
void sub2() {
  printf("Called sub2\n");
}

testit.p6:

use NativeCall;

sub sub1() is native('testlib1') {}
sub sub2() is native('testlib2') {}

sub1();

error:

Cannot locate native library 'libtestlib1.so': ./libtestlib1.so: undefined symbol: sub2

If I call sub2 manually before calling sub1, it works fine, but I don't want to do that..

Curt Tilmes
  • 3,035
  • 1
  • 12
  • 24

2 Answers2

3

Ok, This makes it work, but is a non-portable workaround -- it only works if your MoarVM is built with dyncall. It seems like there should be some exposed function to NativeCall world that does this portably.

use NativeCall;                                                                 

sub dlLoadLibrary(Str --> Pointer) is native {}                                 
dlLoadLibrary('libtestlib2.so');                                                

sub sub1() is native('testlib1') {}                                             

sub1();                                                                         

dlLoadLibrary is the dyncall way to load a dynamic library, which is apparently enough for the symbol to be resolved.

Better suggestion from @jnthn:

sub fake() is native('testlib2');
try fake();

fake() loads testlib2, throws an Exception because fake isn't a real routine in that library, but try ignores the Exception.

Curt Tilmes
  • 3,035
  • 1
  • 12
  • 24
1

This might be a bit naive, but shouldn't the problem be solved at the C or linker level rather than the Perl 6 level? I mean, even in the C code, sub1 won't work. Why would you expect a higher level (Perl 6) to fix the problems of the lower-level code?

moritz
  • 12,710
  • 1
  • 41
  • 63
  • You are correct, it must be solved at the C/linker level. What Perl (or perhaps Rakudo, if NativeCall is more of a Rakudo thing than a Perl thing) needs to offer is a way to direct C/linker to pull in the right library. – Curt Tilmes Mar 01 '18 at 11:51
  • @CurtTilmes you are contradicting yourself. If it needs to be solved at the C/linker level, then it needs to be solved without Rakudo or Perl 6 getting involved. – moritz Mar 02 '18 at 07:04
  • I'm at a loss -- You're right that C/linker needs to pull in the library and symbol, but without a way for Rakudo/Perl 6 to pass in the name of the needed library, how do you propose it is possible? When I say that it must be solved, I mean we need VM level support, this isn't something that can be done strictly high level, but you still need a way to invoke it. – Curt Tilmes Mar 02 '18 at 12:06
  • I'm proposing that you modify the C code to load the library it needs. First make it work in C. When it works in C without external interactions, *then* start thinking about integrating it with Perl 6. – moritz Mar 02 '18 at 15:43
  • It works fine in C... I compile my C program that calls the first library, tell the linker to link in both libraries and everything is fine. We need a way to tell perl to link in both libraries. – Curt Tilmes Mar 02 '18 at 16:18
  • Maybe have the "is native" trait take an array of libraries: "is native(['testlib1', v1], ['testlib2', v2'])" or some such? – Curt Tilmes Mar 02 '18 at 16:24
  • When you are proposing that I modify the C code, note that both library 1 and library 2 are third party libraries. They just say "add -l -l" to your LDFLAGS to use the library. We need a perl way to specify just that. – Curt Tilmes Mar 02 '18 at 16:31