共享库中的函数如何链接未实现的函数?

时间:2009-11-04 14:55:11

标签: shared ld

是否可以创建一个共享库,其中存在一些未实现的函数?

我想创建一个共享库testDele.so并将testDele.so中的一些函数留给其他人使用,例如:

  1. 图书馆提供商制作文件:
  2. ====== testDele.c ==============

    #include <stdlib.h>
    #include "testDele.h"
    const DELE * DELE_Init( void * udata)
    {
       DELE * hnd = (DELE *) malloc(sizeof(DELE));
       hnd->udata = udata;   
       hnd->fun = &priFun;
       return hnd;
    }
    

    ========== testDele.h ==============

    extern int priFun(int a);
    typedef int (*DELE_FUN)(int a);
    typedef struct _dele
    {
       void * udata;
       DELE_FUN fun;
    } DELE ; 
    const DELE * DELE_Init( void * udata);
    
    1. USER-B实现文件
    2. ====== testDeleImp.c ==============

      #inlucde "testDele.h"
      #include <stdio.h>
      int priFun(int a)    
      {
              printf("testDele priFun:a=%d\n",a);
              return 1;    
      }
      

      ====== testDeleMain.c =============

      #include "testDele.h"
      int main()
      {
         DELE * dele = DELE_Init(NULL);
         dele->fun(20);
         free (dele);
         return 1;    
      }
      

      然后当我(共享库提供程序)编译共享库

      % gcc -shared -o libtestDele.so -fPIC testDele.c
      

      发生以下错误

      =============================================== =

      Undefined symbols:
        "_priFun", referenced from:
            _priFun$non_lazy_ptr in cceJPWAA.o
      ld: symbol(s) not found
      collect2: ld returned 1 exit status
      

      我知道这个错误是由未实现的函数priFunc引起的。但是有没有gcc的参数来阻止链接未定义的符号?

2 个答案:

答案 0 :(得分:0)

这绝对有可能,我之前已经这样做了。

我认为它可能是在C ++中。我有一个未实现的函数(这是合法的)被调用并将它们作为静态库链接起来的类,我认为链接作为SO也可以工作..(我也没有像虚函数那样做任何事情)< / p>

我认为您的问题也可能是您从C文件直接转到SO。

首先尝试编译对象(.o)文件,然后将其链接到SO

当我在一个可以访问它的地方时,我会尝试发布一些实际的代码。

答案 1 :(得分:0)

问题是你在DELE_Init中将priFun的地址分配给hnd-&gt; fun。因此链接器必须解析该符号。如果您的代码直接调用函数,那么它可以保持未定义。

extern int priFunc(int);
int deleteFunc(int a)
{
    return priFunc(a);
}

现在您可以将其编译为共享库:

%gcc -shared -o libdelete.so delete.c

注意未定义的符号:

%nm -u libdelete.so
U priFunc

但是,如果主应用程序调用 deleteFunc ,则无法提前编译,因为 priFunc 未解析。您必须在源代码中提供它,以便您的用户进行编译,因为它们具有缺少的功能。

如果要以可执行格式提供库和应用程序。然后我的建议是:

存根解决方案

创建包含所有用户功能的存根共享库。创建库时链接此存根。然后,您的用户在运行时提供他们的库作为替代。

动态库解决方案

坚持使用函数指针。但是使用dlopen()之类的东西来加载用户库和函数。

userlib = argv[1];
dld = dlopen(userlib, RTLD_LAZY);
priFunc = dlsym(dld, "priFun");
delete = DELE_Init(udata, priFunc);
delete->fun(20);