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

发布于 2024-08-09 18:42:31 字数 1508 浏览 4 评论 0原文

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

我想创建一个共享库 testDele.so 并保留 testDele.so 中的一些函数以供其他人实现,例如:

  1. 库提供者制作文件:

====== 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 实现文件

====== 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 是否有任何参数可以防止链接未定义的符号?

Is it possible to make a shared library in which exist some function that are not implemented?

I'l like to make a shared library testDele.so and leave some of the functions in the testDele.so to be implimented by other people for example:

  1. library provider make the files:

====== 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 implements the files

====== 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;    
}

then when I (shared library provider) compile the shared library

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

the following error occured

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

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

I know this error is caused by the un-implemented function priFunc. But is there any parameters of gcc to prevent from linking the undefined symbols?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蝶…霜飞 2024-08-16 18:42:31

这绝对是可能的,我以前就这样做过。

我认为它可能是用 C++ 编写的。我有一个类,其中包含未实现的函数(这是合法的),这些函数被调用并将它们链接为静态库,我认为链接为 SO 也有效。(我也不必做任何类似虚拟函数的事情)

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

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

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

This is definately possible, I have done this before.

I think it may have been in C++ though. I had a class with unimplemented functions(which is legal) that were called and linking them as a static library worked, and I think linking as a SO worked also.. (I didn't have to do anything like virtual functions either)

I think your problem might also be that you are going straight from a C file to an SO.

Try compiling to an object(.o) file first and then linking that into an SO

I'll try to post some actual code in a little bit when I'm at a place with access to it.

娇柔作态 2024-08-16 18:42:31

问题是您在 DELE_Init 中将 priFun 的地址分配给 hnd->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);

The problem is that you are assigning the address of priFun to hnd->fun in DELE_Init. So the linker must resolve the symbol. If your code calls the function directly, then it can be left undefined.

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

Now you can compile this into a shared library:

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

Note the undefined symbol:

%nm -u libdelete.so
U priFunc

However, your main application cannot be compiled ahead of time if it calls deleteFunc because priFunc is unresolved. You must provide it in source code for your user to compile as they have the missing function.

If you want to provide both the library and your application in executable format. Then my suggestions are:

stub solution

Create a stub shared library containing all the user functions. Link against this stub when you create your library. Then your user provide their library as a replacement at run-time.

dynamic library solution

Stick with function pointers. But use something like dlopen() to load user libraries and functions.

userlib = argv[1];
dld = dlopen(userlib, RTLD_LAZY);
priFunc = dlsym(dld, "priFun");
delete = DELE_Init(udata, priFunc);
delete->fun(20);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文