繁体   English   中英

使用g ++进行动态共享库编译

[英]Dynamic Shared Library compilation with g++

我正在尝试使用g ++从Program-Library-HOWTO编译以下简单的DL库示例代码。 这只是一个例子,所以我可以学习如何使用和编写共享库。 我正在开发的库的真正代码将用C ++编写。

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char **argv) {
    void *handle;
    double (*cosine)(double);
    char *error;

    handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
    if (!handle) {
        fputs (dlerror(), stderr);
        exit(1);
    }

    cosine = dlsym(handle, "cos");
    if ((error = dlerror()) != NULL)  {
        fputs(error, stderr);
        exit(1);
    }

    printf ("%f\n", (*cosine)(2.0));
    dlclose(handle);
}

如果我用gcc编译程序,它工作正常。

gcc -o foo foo.c -ldl

当我将文件名和编译器更改为以下内容时

g++ -o foo foo.cpp -ldl

我收到以下错误:

foo.cpp:16:错误:无效转换为'void *'到'double(*)(double)'

我理解(我我理解,如果这是错的,请纠正我)我不能从C ++中的void指针进行隐式转换,但C让我,这就是为什么上面的代码将使用gcc编译但不使用克++。 所以我尝试通过将上面的第16行更改为:

cosine = (double *)dlsym(handle, "cos");

有了这个,我收到以下错误:

foo.cpp:16:错误:在赋值时无法将'double *'转换为'double(*)(double)'

这些问题可能与我自己对正确的C ++编码标准的普遍无知有关。 任何人都可以向我指出一个关于使用C ++示例代码开发Linux动态库的好教程吗?

C允许从void *到任何指针类型(包括函数指针)的隐式转换; C ++需要显式转换。 正如leiflundgren所说,你需要将dlsym()的返回值强制转换为你需要的函数指针类型。

很多人发现C的函数指针语法很尴尬。 一种常见的模式是typedef函数指针:

typedef double (*cosine_func_ptr)(double);

您可以将函数指针变量cosine定义为您的类型的成员:

cosine_func_ptr cosine;

并使用类型而不是笨拙的函数指针语法进行强制转换:

cosine = (cosine_func_ptr)dlsym(handle, "cos");

dlsym返回指向符号的指针。 (作为void*是通用的。)在你的情况下,你应该将它强制转换为函数指针。

 double (*mycosine)(double); // declare function pointer
 mycosine = (double (*)(double)) dlsym(handle, "cos"); // cast to function pointer and assign

 double one = mycosine(0.0); // cos(0)

所以这种罕见的情况之一,编译器错误是一个很好的线索。 ;)

如果编写代码的方式,这实际上更像是一个C问题,但你可以使用C ++。 我没有关于动态共享库的教程(你链接到的网页似乎很好),但是这里是如何用C ++修复你的代码:

  • 声明my_cos是一个将(最终)调用动态加载的余弦函数的函数:

     double my_cos(double); 
  • 将函数指针指定给my_cos

     my_cos = (double (*)(double)) dlsym(handle, "cos"); 

这有点复杂,但它为my_cos分配一个返回double的东西,是取消引用另一个函数指针的结果,并将double作为参数。 正如其他人发布的那样,C ++对代码的显式性的要求比C要高一些。

  • 用std :: cerr或std :: cout替换那个相当过时的fputs消息:

     std::cerr << "error loading library cos: " << error << std::endl; 

std::cout << "result is " << (*my_cos)(2.0)) << std::endl;

希望对此有所帮助。 如果那些怪异的顽皮东西吓到你,我会推荐van Linden的Deep C Secrets,以及C上的Kernighan和Ritchie Book。

编辑:关于如何专门在C ++而不是C中寻找开发指南的评论中的好点,以避免此类问题。 我不知道C ++中的类似指南,但大约99%的C代码可以嵌入到C ++代码中并且工作得很好。 此函数指针大小写是例外之一。

在C ++中,您必须执行reinterpret_cast (而不是C强制转换):

typedef double (* double_from_double_function_t(double));
…
double_from_double_function_t cosine = reinterpret_cast<double_from_double_function_t>(dlsym(handle, "cos"));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM