简体   繁体   English

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

[英]Dynamic Shared Library compilation with g++

I'm trying to compile the following simple DL library example code from Program-Library-HOWTO with g++. 我正在尝试使用g ++从Program-Library-HOWTO编译以下简单的DL库示例代码。 This is just an example so I can learn how to use and write shared libraries. 这只是一个例子,所以我可以学习如何使用和编写共享库。 The real code for the library I'm developing will be written in C++. 我正在开发的库的真正代码将用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);
}

If I compile the program with gcc it works fine. 如果我用gcc编译程序,它工作正常。

gcc -o foo foo.c -ldl

When I change the filename and compiler to the following 当我将文件名和编译器更改为以下内容时

g++ -o foo foo.cpp -ldl

I get the following error: 我收到以下错误:

foo.cpp:16: error: invalid conversion from 'void*' to 'double (*)(double)' foo.cpp:16:错误:无效转换为'void *'到'double(*)(double)'

I understand (I think I understand, correct me if this is wrong) that I can't do an implicit cast from a void pointer in C++, but C lets me, and this is why the above code will compile using gcc but not using g++. 我理解(我我理解,如果这是错的,请纠正我)我不能从C ++中的void指针进行隐式转换,但C让我,这就是为什么上面的代码将使用gcc编译但不使用克++。 So I tried an explicit cast by changing line 16 above to: 所以我尝试通过将上面的第16行更改为:

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

With this in place, I get the following error: 有了这个,我收到以下错误:

foo.cpp:16: error: cannot convert 'double*' to 'double (*)(double)' in assignment foo.cpp:16:错误:在赋值时无法将'double *'转换为'double(*)(double)'

These problems probably have more to do with my own general ignorance of proper C++ coding standards than anything else. 这些问题可能与我自己对正确的C ++编码标准的普遍无知有关。 Can anyone point me to a good tutorial on developing dynamic libraries for Linux that uses C++ example code? 任何人都可以向我指出一个关于使用C ++示例代码开发Linux动态库的好教程吗?

C allows implicit casts from void * to any pointer type (including function pointers); C允许从void *到任何指针类型(包括函数指针)的隐式转换; C++ requires explicit casting. C ++需要显式转换。 As leiflundgren says, you need to cast the return value of dlsym() to the function pointer type you need. 正如leiflundgren所说,你需要将dlsym()的返回值强制转换为你需要的函数指针类型。

Many people find C's function pointer syntax awkward. 很多人发现C的函数指针语法很尴尬。 One common pattern is to typedef the function pointer: 一种常见的模式是typedef函数指针:

typedef double (*cosine_func_ptr)(double);

You can define your function pointer variable cosine as a member of your type: 您可以将函数指针变量cosine定义为您的类型的成员:

cosine_func_ptr cosine;

And cast using the type instead of the awkward function pointer syntax: 并使用类型而不是笨拙的函数指针语法进行强制转换:

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

dlsym returns a pointer to the symbol. dlsym返回指向符号的指针。 (As void* to be generic.) In your case you should cast it to a function-pointer. (作为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)

So this one of these rare cases where the compiler error is a good clue. 所以这种罕见的情况之一,编译器错误是一个很好的线索。 ;) ;)

With the way your code if written, this is really more of a C question, but you can get this to will work in C++. 如果编写代码的方式,这实际上更像是一个C问题,但你可以使用C ++。 I don't have a tutorial for you on Dynamic Shared Libraries (the web page you linked to seems fine), but here's how to fix your code in C++: 我没有关于动态共享库的教程(你链接到的网页似乎很好),但是这里是如何用C ++修复你的代码:

  • declare my_cos to be a function that will (eventually) call the dynamically loaded cosine function: 声明my_cos是一个将(最终)调用动态加载的余弦函数的函数:

     double my_cos(double); 
  • assign the function pointer to my_cos 将函数指针指定给my_cos

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

This is a little complicated, but it's assigning to my_cos something that returns a double, is the result of dereferencing another function pointer, and takes a double as an argument. 这有点复杂,但它为my_cos分配一个返回double的东西,是取消引用另一个函数指针的结果,并将double作为参数。 As other people have posted, C++ is a little more demanding about the explicitness of your code than C. 正如其他人发布的那样,C ++对代码的显式性的要求比C要高一些。

  • replace that rather dated fputs message with a std::cerr or std::cout: 用std :: cerr或std :: cout替换那个相当过时的fputs消息:

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

and

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

Hope that this help. 希望对此有所帮助。 If that weird casty stuff scares you, I'd recommend Deep C Secrets by van Linden, and definitely the Kernighan and Ritchie Book on C. 如果那些怪异的顽皮东西吓到你,我会推荐van Linden的Deep C Secrets,以及C上的Kernighan和Ritchie Book。

Edit: Good point in the comment about how you're specifically looking for a development guide in C++ rather than C to avoid this type of problem. 编辑:关于如何专门在C ++而不是C中寻找开发指南的评论中的好点,以避免此类问题。 I don't know of a comparable guide in C++, but about 99% of C code can be embedded in C++ code and work just fine. 我不知道C ++中的类似指南,但大约99%的C代码可以嵌入到C ++代码中并且工作得很好。 This function pointer case is one of the exceptions. 此函数指针大小写是例外之一。

In C++, you have to perform a reinterpret_cast (not a C cast): 在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