I'm writing a pty native extension and want to link libutil so that I may use forkpty and openpty from <pty.h>
.
I'm using the two commands taken from the official guide:
g++ -fPIC -lutil -I/home/crunchex/work/dart-sdk -c pty.cc -o pty.o
gcc -shared -Wl,-soname,libpty.so -o libpty.so pty.o
and I'm getting the following error:
/home/crunchex/work/dart-sdk/bin/dart: symbol lookup error: /home/crunchex/work/pty/bin/packages/pty/libpty.so: undefined symbol: forkpty
This may be more of a g++/gcc question, but as far as I can tell I'm doing that part right by adding -lutil and including <pty.h>
. libutil.so is installed on my Ubuntu 14.04 system, so I'm fairly certain it's there.
Here's my test extension:
#include <string.h>
#include <pty.h>
#include "include/dart_api.h"
Dart_NativeFunction ResolveName(Dart_Handle name,
int argc,
bool* auto_setup_scope);
DART_EXPORT Dart_Handle pty_Init(Dart_Handle parent_library) {
if (Dart_IsError(parent_library)) {
return parent_library;
}
Dart_Handle result_code =
Dart_SetNativeResolver(parent_library, ResolveName, NULL);
if (Dart_IsError(result_code)) {
return result_code;
}
return Dart_Null();
}
Dart_Handle HandleError(Dart_Handle handle) {
if (Dart_IsError(handle)) {
Dart_PropagateError(handle);
}
return handle;
}
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//
void PtyFork(Dart_NativeArguments args) {
Dart_EnterScope();
struct winsize winp;
winp.ws_col = 80;
winp.ws_row = 24;
winp.ws_xpixel = 0;
winp.ws_ypixel = 0;
int master = -1;
char name[40];
pid_t pid = forkpty(&master, name, NULL, &winp);
Dart_ExitScope();
}
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//
struct FunctionLookup {
const char* name;
Dart_NativeFunction function;
};
FunctionLookup function_list[] = {
{"PtyFork", PtyFork},
{NULL, NULL}};
Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope) {
if (!Dart_IsString(name)) return NULL;
Dart_NativeFunction result = NULL;
Dart_EnterScope();
const char* cname;
HandleError(Dart_StringToCString(name, &cname));
for (int i=0; function_list[i].name != NULL; ++i) {
if (strcmp(function_list[i].name, cname) == 0) {
result = function_list[i].function;
break;
}
}
Dart_ExitScope();
return result;
}
Copied from https://code.google.com/p/dart/issues/detail?id=22257#c4
The problem is that
libutil
, part oflibc6
, needs to be linked into your native extension shared library on the link command line, not the compile command line.First, the
-lutil
library specification should go on the linking line, rather than the compiling line:gcc -shared -Wl,-soname,libpty.so -o libpty.so pty.o -lutil
This puts a dependency on the shared library
libutil.so
into your shared library, and when it is loaded by dlload, the dependencies are also loaded and linked.This fails unless the
-lutil
option is put afterpty.o
on your commandline, since linked libraries must be put in reverse dependency order on the linker command line.
After doing this, the output of objdump on libpty.so includes:
and running the test program main.dart no longer fails.
If you don't want to link a shared library into your library, then you need a static library, but there are many problems with this - it is not impossible, but much harder. Then, the problem is that you may only have libutil.so on your system, not
libutil.a
, so your shared library will need to load libutil when it is loaded.The
dlopen
function used by Dart to load your shared library shouldrecursively load other shared libraries it depends on, but this may or may not be working. When I compile with
-lutil
in the link step, the shared libraries shown by ldd libpty.so are just libc.so.6, and some standard linker ones ld-linux-.. and linux-vdso. So I don't see libutil there.To link the functions you need statically into your shared library, you
would need something like
But since the
libutil.a
in the distribution is not compiled with -wPIC
, it can't be linked into a shared library:I think the best bet is to make the shared library dependency upon
libutil.so
work.