1

私は pty のネイティブ拡張機能を作成しており、.libutil をリンクして forkpty と openpty を使用できるようにしたいと考えてい<pty.h>ます。

私は公式ガイドから取られた2つのコマンドを使用しています:

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

次のエラーが表示されます。

/home/crunchex/work/dart-sdk/bin/dart: symbol lookup error: /home/crunchex/work/pty/bin/packages/pty/libpty.so: undefined symbol: forkpty

これは g++/gcc に関する質問かもしれませんが、私が知る限り、 -lutil を追加して<pty.h>. libutil.so は私の Ubuntu 14.04 システムにインストールされているので、そこにあると確信しています。

これが私のテスト拡張です:

#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;
}
4

2 に答える 2

1

https://code.google.com/p/dart/issues/detail?id=22257#c4からコピー

問題はlibutil、 の一部である をlibc6、コンパイル コマンド ラインではなく、リンク コマンド ラインでネイティブ拡張共有ライブラリにリンクする必要があることです。

まず、-lutilライブラリの仕様は、コンパイル行ではなく、リンク行に記載する必要があります。 gcc -shared -Wl,-soname,libpty.so -o libpty.so pty.o -lutil

これにより、共有ライブラリlibutil.soへの依存関係が共有ライブラリに配置され、dlload によって読み込まれると、依存関係も読み込まれてリンクされます。

リンクされたライブラリは、リンカー コマンド ラインで逆の依存関係の順序で配置する必要があるため、コマンドラインで-lutilオプションを後に配置しない限り、これは失敗します。pty.o

これを行った後、libpty.so の objdump の出力には以下が含まれます。

   objdump -x libpty.so 
Dynamic Section: 
   NEEDED               libutil.so.1 
   NEEDED               libc.so.6 
   SONAME               libpty.so 
   INIT                 0x00000000000009c0 
   FINI                 0x0000000000000db4 
   INIT_ARRAY           0x0000000000201dd0 
.... 
Version References: 
   required from libutil.so.1: 
     0x09691a75 0x00 04 GLIBC_2.2.5 
   required from libc.so.6: 
     0x09691a75 0x00 03 GLIBC_2.2.5 
     0x0d696914 0x00 02 GLIBC_2.4 
.... 
0000000000000000  w      *UND*        0000000000000000               
_ITM_registerTMCloneTable 
0000000000000000       F *UND*        0000000000000000               
forkpty@@GLIBC_2.2.5 
0000000000000000  w    F *UND*        0000000000000000               
__cxa_finalize@@GLIBC_2.2.5 
00000000000009c0 g     F .init        0000000000000000              _init 

テスト プログラム main.dart の実行が失敗しなくなりました。

共有ライブラリをライブラリにリンクしたくない場合は、静的ライブラリが必要ですが、これには多くの問題があります-不可能ではありませんが、はるかに困難です. 次に、問題は、あなたのシステムには ではなく libutil.so しかないかもしれないということですlibutil.a。そのため、共有ライブラリはロード時に libutil をロードする必要があります。

dlopenDart が共有ライブラリをロードするために使用する関数は
、依存する他の共有ライブラリを再帰的にロードする必要がありますが、これは機能する場合と機能しない場合があります。リンクステップでコンパイルすると-lutil、ldd libpty.so によって表示される共有ライブラリは libc.so.6 と、いくつかの標準リンカ ld-linux-.. および linux-vdso です。そのため、そこに libutil が表示されません。

必要な関数を共有ライブラリに静的にリンクするには、次の
ようなものが必要です

gcc -shared -Wl,-whole-archive /usr/lib/x86_64-linux-gnu/libutil.a   
-Wl,-no-whole-archive -Wl,-soname,libpty.so -o libpty.so pty.o 

しかしlibutil.a、ディストリビューションの は - でコンパイルされてwPICいないため、共有ライブラリにリンクすることはできません:

/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libutil.a(login.o): relocation   
R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC 
/usr/lib/x86_64-linux-gnu/libutil.a(login.o): error adding symbols: Bad   
value 

最善の策は、共有ライブラリを
libutil.so仕事に依存させることだと思います。

于 2015-02-05T10:53:29.457 に答える