如何通过.def文件的方式导出类

本文介绍了一种通过模板类实现在DLL中导出多实例类的方法,并提供了具体的代码示例,包括定义模板类、创建工厂函数及其实现,以及如何在客户端调用这些导出的模板类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看了许多资料,大部分都是通过__declspec(dllexport) 修饰符进行导出的。
通过.def文件导出函数和类都可以实现,但是导出模板函数和模板类却没有找到,但是没关系。

例子:

dll_test.h


#ifndef DLL_TEST_H
#define DLL_TEST_H


#define  DLL_EXPORT __declspec(dllexport)

#include<string>
using namespace std;


template<typename Dtype> class Operation
{
public:
    virtual Dtype getResult(Dtype a, Dtype b) = 0;
    virtual void destorySelf() { this->~Operation(); }
    virtual ~Operation() {};
};

template<typename Dtype> class OperationSub :public Operation<Dtype>
{
public:
    Dtype getResult(Dtype a, Dtype b);

};

template<typename Dtype> class OperationMul : public Operation<Dtype>
{
public:
    Dtype getResult(Dtype a, Dtype b);

};

//导出工厂函数
template<typename Dtype>  Operation<Dtype> *  createOperator(string oper); 

template<> DLL_EXPORT Operation<float> *  createOperator(string oper); //模板特化声明

template<> DLL_EXPORT Operation<double> *  createOperator(string oper); //模板特化声明


#endif

dll_test.cpp


#include"dll_test.h"


template<typename Dtype> Dtype OperationSub<Dtype>::getResult(Dtype a, Dtype b) { return (a - b); }
template<typename Dtype> Dtype OperationMul<Dtype>::getResult(Dtype a, Dtype b) { return (a * b); }


template<typename Dtype>  Operation<Dtype> *  createOperator (string oper) 
{
    if (strcmp(oper.c_str(), "-")== 0)
    {
        return new OperationSub<Dtype>();
    }
    else if (strcmp(oper.c_str(), "*") == 0)
    {
        return new OperationMul<Dtype>();
    }

}

// 模板特化 float 
template<> DLL_EXPORT Operation<float> * createOperator(string oper)
{
    if (strcmp(oper.c_str(), "-") == 0)
    {
        return new OperationSub<float>();
    }
    else if (strcmp(oper.c_str(), "*") == 0)
    {
        return new OperationMul<float>();
    }
}


// 模板特化 double
template<> DLL_EXPORT Operation<double> * createOperator(string oper)
{
    if (strcmp(oper.c_str(), "-") == 0)
    {
        return new OperationSub<double>();
    }
    else if (strcmp(oper.c_str(), "*") == 0)
    {
        return new OperationMul<double>();
    }
}

测试函数:
将上面的代码编译生成动态库dll,将文件.h,lib,dll添加到测试函数所在的工程。
test.cpp

#include"dll_test.h"
#include<string>
#include<iostream>
//#pragma comment(lib,"dll_test.lib")

int main()
{
    Operation<float> *foper = createOperator<float>("-");
    Operation<double> *doper = createOperator<double>("*");

    float fresult = foper->getResult(10, 5);
    double dresult = doper->getResult(10, 5);

    cout << fresult << endl;
    cout << dresult << endl;
}

参考文献:
1. http://forums.codeguru.com/showthread.php?364061-How-to-export-c-class-in-DLL-using-DEF-file
2. https://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL [HowTo: Export C++ classes from a DLL]
3. http://www.mingw.org/wiki/exporting_a_class_from_a_dll_for_multiple_instantiations

<think>好的,用户现在想了解如何使用gendef工具生成原始的.def文件,特别是针对已有的dcmtk.dll。之前我已经给过他们转换库文件的步骤,其中提到了gendef,现在需要详细说明这部分。 首先,我需要确认用户的环境。他们可能使用的是Windows系统,并且已经安装了MinGW工具链,因为之前提到Qt的dlltool。所以步骤里需要确保他们能找到gendef,这个工具通常包含在MinGW的utils里,或者可能需要单独安装。比如在MSYS2里,可以通过包管理器安装,这点需要提醒用户。 接下来,用户可能遇到的问题是没有安装gendef,或者路径没有正确设置。所以步骤里需要包括如何安装和检查gendef是否存在。同时,生成def文件时可能需要管理员权限,特别是如果dcmtk.dll在系统目录下,但一般用户目录可能不需要,不过还是提醒一下以预防权限问题。 然后,具体生成命令是`gendef dcmtk.dll`,但需要解释每个参数的作用,比如如果有多个架构的dll,是否需要指定。另外,生成后的def文件可能需要处理名称修饰,所以可能需要后续步骤,比如使用dlltool的--kill-at选项,但用户现在的问题只是生成def,这部分可以在常见问题里提到。 用户可能的疑问包括生成的def文件是否完整,或者出现错误怎么办。比如,如果dll没有导出函数,或者权限不足,或者架构不匹配。这时候需要给出解决方法,比如检查dll是否有效,使用Dependency Walker查看导出函数,或者安装正确的工具链。 另外,用户可能不知道如何验证生成的def文件是否正确,所以需要指导他们用文本编辑器查看是否有导出函数列表,或者用nm工具检查符号是否存在。同时,提醒如果def文件内容为空,需要检查dll是否正确,或者是否有导出符号。 最后,补充一些注意事项,比如不同架构的兼容性,确保生成的def和后续的.a文件架构一致。可能用户之后会用这个def文件生成.a,所以提前考虑后续步骤可能出现的问题,并在当前回答中给出预防措施。</think>以下是如何使用`gendef`工具从`.dll`文件生成原始`.def`文件的详细步骤说明: --- ### **操作步骤** 1. **环境准备**: - 安装`gendef`工具: - 若使用**MSYS2**环境: ```bash pacman -S mingw-w64-x86_64-tools-git # 64位系统 pacman -S mingw-w64-i686-tools-git # 32位系统 ``` - 工具默认路径:`MSYS2安装目录/usr/bin/gendef.exe` 2. **定位目标.dll文件**: ```bash cd /path/to/dcmtk.dll # 进入.dll文件所在目录 ``` 3. **执行生成命令**: ```bash gendef dcmtk.dll # 生成同名.def文件 ``` *生成成功后,当前目录会生成`dcmtk.def`* 4. **指定架构(可选)**: ```bash gendef -a x86_64 dcmtk.dll # 明确指定64位DLL gendef -a i386 dcmtk.dll # 指定32位DLL ``` --- ### **验证生成结果** 1. **检查文件内容**: ```bash cat dcmtk.def ``` - 正常输出应包含导出函数列表,例如: ``` EXPORTS DcmTKFunction1 DcmTKFunction2 ... ``` 2. **常见有效内容标识**: - `EXPORTS`段开头 - 包含实际函数名(可能带有名称修饰,如`_DcmTKFunction@4`) --- ### **常见问题处理** 1. **生成空文件/无导出函数**: - 检查DLL有效性: ```bash objdump -x dcmtk.dll | grep "Export Directory" ``` - 使用GUI工具验证(如`Dependency Walker`) 2. **权限不足错误**: ```bash # 以管理员身份运行终端(Windows) chmod +rw dcmtk.dll ``` 3. **名称修饰问题**: - 若函数名含`@`或`_`前缀,需后续处理: ```bash dlltool --kill-at -d dcmtk.def -l dcmtk.a ``` --- ### **技术原理** `gendef`通过解析PE格式的.dll文件导出表,提取以下关键信息: $$ \text{导出函数名} + \text{序号} \xrightarrow{\text{文本化}} .def文件 $$ 生成的`.def`文件记录了动态库的符号暴露规则,为后续构建`.a`导入库提供基础。 --- ### **注意事项** 1. **架构匹配**:确保`gendef`工具与.dll文件的位数一致(32/64位) 2. **名称保留**:若需保留C++名称修饰(如成员),不要使用`--kill-at` 3. **二次编辑**:可手动编辑.def
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值