在 .so 库中使用 C++ 类

Using C++ classes in .so libraries

提问人:Flame 提问时间:9/12/2008 最后编辑:frogattoFlame 更新时间:6/2/2016 访问量:25182

问:

我正在尝试为 C++ 课程编写一个小班库。

我想知道是否可以在我的共享对象中定义一组类,然后直接在我的演示库的主程序中使用它们。有什么技巧吗?我记得很久以前(在我开始真正编程之前)读到过 C++ 类只能使用 MFC .dll,而不能使用普通的 .dll,但这只是窗口方面。

C++ Linux 类库

评论


答:

12赞 3 revs, 2 users 90%Kristopher Johnson #1

C++ 类在 .so 共享库中工作正常(它们也适用于 Windows 上的非 MFC DLL,但这并不是您的问题)。它实际上比 Windows 更容易,因为您不必从库中显式导出任何符号。

本文档将回答您的大多数问题: http://people.redhat.com/drepper/dsohowto.pdf

要记住的主要事情是在编译时使用该选项,在链接时使用该选项。你可以在网上找到很多例子。-fPIC-shared

4赞 Adam Pierce 9/12/2008 #2

据我了解,只要您链接所有使用同一编译器编译的 .so 文件,这就可以了。不同的编译器以不同的方式修改符号,并且无法链接。

这是在 Windows 上使用 COM 的优点之一,它定义了将 OOP 对象放入 DLL 的标准。我可以使用 GNU g++ 编译 DLL 并将其链接到使用 MSVC 编译的 EXE - 甚至 VB!

评论

1赞 Ben Collins 9/16/2008
有一点需要注意:如果满足以下条件,您可以使用包含由不同编译器编译的 C++ 代码的共享库:(a) 符号修改方案匹配或 (b) 您有一些函数可以用作 API 粘合剂。extern C
10赞 Flame 9/12/2008 #3

我的解决方案/测试

这是我的解决方案,它符合我的预期。

法典

货号 hh

#include <string>

class Cat
{
    std::string _name;
public:
    Cat(const std::string & name);
    void speak();
};

猫 .cpp

#include <iostream>
#include <string>

#include "cat.hh"

using namespace std;

Cat::Cat(const string & name):_name(name){}
void Cat::speak()
{
    cout << "Meow! I'm " << _name << endl;
}

主 .cpp

#include <iostream>
#include <string>
#include "cat.hh"

using std::cout;using std::endl;using std::string;
int main()
{
    string name = "Felix";
    cout<< "Meet my cat, " << name << "!" <<endl;
    Cat kitty(name);
    kitty.speak();
    return 0;
}

汇编

首先编译共享库:

$ g++ -Wall -g -fPIC -c cat.cpp
$ g++ -shared -Wl,-soname,libcat.so.1 -o libcat.so.1 cat.o

然后使用库中的类编译主可执行文件或 C++ 程序:

$ g++ -Wall -g -c main.cpp
$ g++ -Wall -Wl,-rpath,. -o main main.o libcat.so.1 # -rpath linker option prevents the need to use LD_LIBRARY_PATH when testing
$ ./main
Meet my cat, Felix!
Meow! I'm Felix
$

评论

11赞 Michael Shaw 9/4/2013
此代码显示属于共享库中 C++ 类的“陷阱”之一。在“共享”接口中使用 STL 类意味着库和应用程序各自编译自己的 STL 类“string”实现。如果这两个项目在同一台机器上使用相同的编译器同时编译,那么一切看起来都很好。编译库,等待 18 个月,然后编译应用程序,它“可能”工作。但不能保证。将您的共享库以二进制形式分发给其他开发人员,您将遇到“问题”
1赞 CraigDavid 7/22/2020
正如其他人所建议的那样,这种方法是有缺陷的,因为编译器之间的名称篡改差异。我找到了一个很好的资源,似乎显示了正确的方法(第 3.3 节):tldp.org/HOWTO/C++-dlopen/thesolution.html