0

私はオンラインブックBasics of libuvを読んでいて、libuv ライブラリへの静的リンクと動的リンクの両方で動作するようにそれらを書き直そうとしています。ウォッチャーの例 (以下のコード)を書き直しましたが、機能させるために libuv.dylib から取得した関数の名前を「変更」する必要がありました。どういうわけか同じ関数名を保持できますか?

コードを次のようにしたい。

#include <stdio.h>
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
#endif

int64_t counter = 0;

void wait_for_a_while(uv_idle_t *handle, int status) {
  counter++;
  if (counter >= 10e6)
    uv_idle_stop(handle); // This function pointer must be a global variable
}

int main(int argc, char **argv) {
  uv_idle_t idler;

// Initialize code needed for dynamically-linked library
#ifdef DYNAMIC
  void *lib_handle = dlopen("libuv.dylib", RTLD_LOCAL|RTLD_LAZY);
  // Set up pointers to functions defined in libuv.dyld ...
#endif

  uv_idle_init(uv_default_loop(), &idler);
  uv_idle_start(&idler, wait_for_a_while);

  printf("Idling...\n");
  uv_run(uv_default_loop(), UV_RUN_DEFAULT);

// Clean up dynamically linked code
#ifdef DYNAMIC
  dlclose(lib_handle);
#endif
  return 0;
}

現在、こんな感じです。

#include <stdio.h>
#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
// Currently, I need to define function pointers with different names
// than the functions they call
uv_loop_t* (*uln)(void);
int (*ur)(uv_loop_t*, uv_run_mode);
uv_loop_t* (*udl)(void);
int (*uii)(uv_loop_t*, uv_idle_t*);
int (*uist)(uv_idle_t*, uv_idle_cb);
int (*uisp)(uv_idle_t*);
#endif

int64_t counter = 0;

void wait_for_a_while(uv_idle_t *handle, int status) {
  counter++;
  if (counter >= 10e6)
#ifdef DYNAMIC
    uisp(handle);
#else
    uv_idle_stop(handle); // This should be the only line remaining
#endif
}

int main(int argc, char **argv) {
  uv_idle_t idler;

// Code path for dynamic linking case
#ifdef DYNAMIC
  void *lib_handle = dlopen("libuv.dylib", RTLD_LOCAL|RTLD_LAZY);
  // Retrieve symbol names from libuv.dylib
  *(void **)(&uln) = dlsym(lib_handle, "uv_loop_new");
  *(void **)(&ur) = dlsym(lib_handle, "uv_run");
  *(void **)(&udl) = dlsym(lib_handle, "uv_default_loop");
  *(void **)(&uii) = dlsym(lib_handle, "uv_idle_init");
  *(void **)(&uist) = dlsym(lib_handle, "uv_idle_start");
  *(void **)(&uisp) = dlsym(lib_handle, "uv_idle_stop");

  uii(udl(), &idler);
  uist(&idler, wait_for_a_while);

  printf("Idling...\n");
  ur(udl(), UV_RUN_DEFAULT);

  dlclose(lib_handle);

// Code for static linking case
#else
  uv_idle_init(uv_default_loop(), &idler);
  uv_idle_start(&idler, wait_for_a_while);

  printf("Idling...\n");
  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
#endif
  return 0;
}
4

1 に答える 1

2

変化する:

#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
/*...*/

の中へ:

#ifndef DYNAMIC
#include <uv.h>
#else
#include <dlfcn.h>
/*...*/

これで、関数ポインター変数に、呼び出したいインターフェイスと同じ名前を付けることができます。

ただし、なぜこれを行う必要があるのか​​ は不明です。通常は、アプリケーションを動的ライブラリにリンクするだけです。動的ライブラリの実装を実験的に変更する (プラグインのように扱う) 場合にのみ、現在行っていることを行う必要があります。


コメントで、 の構造体の定義が必要であると述べています<uv.h>DYNAMIC次に、元の提案を機能させるには、ヘッダー ファイルを使用しないため、 の場合はこれらの構造を再定義する必要があります。ただし、uvライブラリが変更された場合、それらの変更が失われ、DYNAMICバージョンを一致するように更新する必要があります。これは望ましくない状況です。

もう 1 つの回避策は、異なる関数ポインター名を定義する元のアプローチに従いますが、マクロを定義して元の関数名を関数ポインター名にマップすることです。

#include <uv.h>
#ifdef DYNAMIC
#include <dlfcn.h>
uv_loop_t* (*uln)(void);
int (*ur)(uv_loop_t*, uv_run_mode);
//...
#define uv_loop_new uln 
#defin uv_run ur
//...
#endif
于 2013-07-22T21:54:01.450 に答える