2009-01-27 102 views
11

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

#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: error: invalid conversion from 'void*' to 'double (*)(double)'

我了解(我认为我明白,如果指正这是错误的),我不能在C++中使用void指针进行隐式转换,但C让我,这就是为什么上面的代码将使用gcc编译而不是使用usin g g ++。因此,我通过改变上述行16试过一个显式的:

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

有了这个地方,我得到以下错误:

foo.cpp:16: error: cannot convert 'double*' to 'double (*)(double)' in assignment

这些问题可能有更多的事情要做我自己一般的无知适当的C++编码标准。任何人都可以点我一个关于开发使用C++示例代码的Linux动态库的好教程吗?

+0

我建议通过“在C++中思考”来加快C++的速度。正如你正确的发现,你不能隐式地从void *转换到C++中的其他指针,这意味着你真的只需要在C++而不是其他区域上加快速度:) – workmad3 2009-01-27 15:34:14

+0

谢谢,我正在阅读C++ Primer在业余时间,但现在我有一个项目到期。 – 2009-01-27 15:36:12

回答

24

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"); 
9

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) 

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

+0

您的函数指针声明不是。 – Arkadiy 2009-01-27 15:41:53

+0

这适用于double(* cosine)(double);从原始代码,但不是你提供的函数指针声明。由于我是一个无知的人在这里提问,我不认为我应该改变你的代码。 :) – 2009-01-27 15:46:27

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

  • 替换而过时的fputs消息,一个std :: CERR或std ::法院:

    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++代码中,并且工作得很好。这个函数指针的情况是一个例外。