VC6 DLL 导出构造函数的问题!高手进

fietiger 2009-10-21 01:12:35
最近钻研DLL导出函数的问题,我想导出构造函数,然后被客户显示调用。我的代码如下:
//声明虚基类,相当于是一个接口。
class TestBase
{
public:
TestBase();
virtual void Test() = 0;
virtual ~TestBase();

};
//声明子类
class TesCla :public TestBase
{
public:
TesCla();
virtual ~TesCla();

void Test();
float m_fval;

};
以上代码是写在一个DLL里的,该DLL的def是这样的
CA = ??0TesCla@@QAE@XZ @1
这样就导出了TesCla的构造函数。
通过Depends可以看出确实CA被导出了
在客户代码里,我的代码是这样的:
HMODULE hMod = LoadLibrary("TDll.dll");//显式调用DLL,
typedef TestBase* (*PExportedFn)(void); //定义函数指针
PExportedFn pfnEF= NULL;
pfnEF= (PExportedFn)GetProcAddress(hMod,"CA"); //显式加载函数,该函数是子类的构造函数
if (pfnEF)
{
CXSingleton<CXLoger>::Instance()->Log(INFOLOG,"Load CA");//输出log
}
TestBase* x = NULL;//声明基类指针
x = pfnEF();//通过指针调用子类构造函数
x->Test();//测试函数
delete x;//通过delete释放资源,测试析构函数。
为了测试子类和父类的构造函数及析构函数的调用情况,父类及子类的实现代码如下:

//基类

TestBase::TestBase()
{
CXSingleton<CXLoger>::Instance()->Log(INFOLOG,"Construct TestBase");

}

TestBase::~TestBase()
{
CXSingleton<CXLoger>::Instance()->Log(INFOLOG,"DisConstruct ~TestBase");

}


//子类
TesCla::TesCla()
{
m_fval = 10.0;
CXSingleton<CXLoger>::Instance()->Log(INFOLOG,"Construct TesCla");
CXSingleton<CXLoger>::Instance()->Log(INFOLOG,"m_fval = %.4f",m_fval);

}

TesCla::~TesCla()
{
CXSingleton<CXLoger>::Instance()->Log(INFOLOG,"DiSConstruct ~TesCla");
}
void TesCla::Test()
{
CXSingleton<CXLoger>::Instance()->Log(INFOLOG,"Test in TesCla");
}
结果显示竟然可以用:
2009-10-21 13:3:29 Info Load CA
2009-10-21 13:3:29 Info Construct TestBase
2009-10-21 13:3:29 Info Construct TesCla
2009-10-21 13:3:29 Info m_fval = 10.0000
2009-10-21 13:3:29 Info Test in TesCla
2009-10-21 13:3:29 Info DiSConstruct ~TesCla
2009-10-21 13:3:29 Info DisConstruct ~TestBase

这表明通过显式调用的方法调用的子类的构造函数,而在delete的时候以调用了子类的析构函数。
接着我就把这种用法推广了,结果第一个推广的DLL里就出了问题。
通过类似的判断我发现也能够调用子类的构造函数,只是程序莫名其妙就退出了,析构函数等都没有调用。

请问:为什么不能够将这种方法推广呢?

...全文
289 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
老邓 2009-10-22
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 taodm 的回复:]
老邓真的试过“实在要用容器类,可以使用指针”???
[/Quote]
在一个工程里用过的。
只暴露容器的指针给用户,VC编译器不会发出警告。
运行时也没有断言错误。
lizzoe 2009-10-22
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 loaden 的回复:]
如果一定要导出class,不是不可以!
条件是:成员变量不要有STL的容器类!
实在要用容器类,可以使用指针。
[/Quote]
顶一个
butwang 2009-10-22
  • 打赏
  • 举报
回复
还是按照 COM 的规范来写好,这样其他语言都可以来调用,COM是更好的C++,
百事烟 2009-10-21
  • 打赏
  • 举报
回复
是什么都不重要,假想如此用C++导出的类,delhpi和VB根本不认识啊
还是不要这么导了,意义不大啊

Dll导出普通的函数其它语言是认识的,DLL存在是有意义的

COM导出的组件其它语言也是认识的在C++中COM组件约等C++类
其它语言写的COM和DLL 在C++中也认识,这样才有意义
fietiger 2009-10-21
  • 打赏
  • 举报
回复
呵呵,我是在想那个构造函数编译后的表现形式是什么?
百事烟 2009-10-21
  • 打赏
  • 举报
回复
又想了一下,看来COM导出组件那么麻烦是有道理的,不用二进制真地还导不出来,呵呵~
枫桦沐阳 2009-10-21
  • 打赏
  • 举报
回复
构造函数是虚函数,导不出来。

参照
http://topic.csdn.net/u/20090804/14/a97835b6-0bf4-4cd0-a41b-080409ab341b.html
M_S_D_N 2009-10-21
  • 打赏
  • 举报
回复
哈哈,楼主跟我一样疯狂哈。

我曾经这样到处C++类成员函数:

;?Login@CWC@@QAEHPBG00AAW4_WS_C_G@@AAW4_WS_L_R@@@Z=
?Login@CWC@@QAEHPB_W00AAW4_WS_C_G@@AAW4_WS_L_R@@@Z

不过我是迫不得已啊,因为我是用VC6,却要使用一个由VS2008编译出来的dll导出类,而这两个版本编的C++函数格式居然有点小差别,故出此下策。。。
百事烟 2009-10-21
  • 打赏
  • 举报
回复
迷糊,看错题了,是导构造函数
构造函数好像导不出来吧?
百事烟 2009-10-21
  • 打赏
  • 举报
回复
导出类
1. DLL工程的cpp
#include <iostream>
using namespace std;

#define DLLAPI extern "C" _declspec(dllexport)
#include "DllCode.h"

class CB: public CA
{
public:
CB::CB(char *str){ m_pBuf = str; }
CB::~CB(){}
virtual char *GetStr(){ return m_pBuf;}
virtual void test(){ printf("testtesttesttesttest\n");}
private:
char *m_pBuf;
};

DLLAPI void InitObj(char *str, CA** pCA)
{
CB* pCB = new CB(str);
*pCA = (CA*)pCB;
}

DLLAPI void FreeObj(CA *pCA)
{
delete (CB*)pCA;
}


2. Dll工程的.h
#ifdef DLLAPI
#else
#define DLLAPI extern "C" _declspec(dllimport)
#endif

class CA
{
public:
virtual char *GetStr() = 0;
virtual void test() = 0;
};

DLLAPI void InitObj(char *str, CA** pCA);
DLLAPI void FreeObj(CA *pCA);


3. DLL工程的def
EXPORTS
InitObj
FreeObj


4. EXE工程只有1个CPP
#pragma comment(lib, "../SampleDll/Debug/SampleDll.lib")
#include "../SampleDll/DllCode.h"

#include <iostream>
using namespace std;

int main()
{
CA *pCA = NULL;
InitObj("TestClassOK~!", &pCA);
printf("%s\n", pCA->GetStr());
pCA->test();
FreeObj(pCA);
getchar();
return 0;
}
arong1234 2009-10-21
  • 打赏
  • 举报
回复
哈哈,个人认为只要是实例化的模板,没有什么不可以用的,也就是说

template <typename T> __declspec(dllexport) class A
{
}; //这是不行的,你不能导出partial类

但是__declspec(dllexport) class A
{

vector<int> a; //这个个人认为应该可以。
};
[Quote=引用 5 楼 taodm 的回复:]
老邓真的试过“实在要用容器类,可以使用指针”???
[/Quote]
taodm 2009-10-21
  • 打赏
  • 举报
回复
老邓真的试过“实在要用容器类,可以使用指针”???
老邓 2009-10-21
  • 打赏
  • 举报
回复
如果一定要导出class,不是不可以!
条件是:成员变量不要有STL的容器类!
实在要用容器类,可以使用指针。
arong1234 2009-10-21
  • 打赏
  • 举报
回复
而且没有听说扩展dll可以用def来操作的,它应该是通过_declspec直接导出,并且必须使用lib来静态链接的
  • 打赏
  • 举报
回复
........
别在导出class这个事情上浪费时间了。
taodm 2009-10-21
  • 打赏
  • 举报
回复
珍惜生命,远离扩展dll,只使用纯C接口的标准dll

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧