dll 导出 vcl 类???

w88529593 2008-10-16 11:18:10
如题,谁做过这样的测试例子,可以讲讲如何实现吗?就是新建个Dll工程,选择支持Vcl,然后 新建个From1,在类前声明为导出类: __declspec(dllexport) __stdcall class TForm1 : public TForm ,但是再新建个Exe程序,如何使用DLL中的这个导出类TForm1呢?
...全文
106 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
w88529593 2008-10-17
  • 打赏
  • 举报
回复
呵呵,搞不明白,睡觉都不安心
yuanreid 2008-10-17
  • 打赏
  • 举报
回复
都半夜了,都不容易啊
w88529593 2008-10-17
  • 打赏
  • 举报
回复
谢谢伙计哦,参考一下,看起来想实现这个,还挺麻烦的
laowang2 2008-10-17
  • 打赏
  • 举报
回复
建议做成ActiveX的 Dll
yuanreid 2008-10-16
  • 打赏
  • 举报
回复
动态加载并生成类,使用类的成员函数:
1) 需解决的问题:
需解决的第一个问题是C++成员函数在输出时的名称不是定义类时的成员函数的名称,没办法直接通过成员函数名称获取函数指针;这个问题可以通过在作动态连接库时在.def文件中定义输出成员函数名称解决,方法如下实例:
EXPORTS
ConstructorOfA0 = ??0A@@QAE@XZ PRIVATE
ConstructorOfA2 = ??0A@@QAE@H@Z PRIVATE
SetNumOfA = ?SetNum@A@@UAEXH@Z PRIVATE
DestructorOfA = ??1A@@UAE@XZ PRIVATE
第二个问题是成员函数的指针不能进行强制类型转换转换为其他类型,这可以利用template 和union的便捷性解决,示例如下:
转换函数的定义如下:
template
Dest force_cast(Src src)
{
union
{
Dest d;
Src s;
} convertor;
convertor.s = Src;
return convertor.d;
}
转换函数的使用方法如下所示:
typedef void (A::*PSetNum)(int);
FARPROC fp;
.
PSetNum psn = force_cast<PSetNum>(fp);

2) 动态连接库的创建:
a) 首先按原来的方法创建动态连接库的工程文件、头文件和源文件(注意输出函数要定义为虚函数,不需输出的函数不要定义为虚函数,构造函数不能为虚函数,但其和虚函数使用接近),并编译;
b) 在其他地方创建一工程,动态调用动态连接库,把动态连接库的头文件包含进去,并在该工程的一个源文件中定义一个动态连接库的虚函数,然后编译,编译时提示出错,在出错信息中找到每个成员函数的输出名称(可修改后找到没出错的虚函数输出名称);
c)
在定义文件(.def)中添加输出声明:
EXPORTS
ConstructorOfA0 = ??0A@@QAE@XZ PRIVATE
ConstructorOfA0为任意定义的函数名,在程序调用成员函数时通过该名称获取函数指针,该名称不作规定,以记忆方便为准;
??0A@@QAE@XZ为上一步查出的成员函数输出名称;
d) 最后进行编译,生成动态连接库;
3) 动态连接库的调用:
a)
在调用动态连接库工程的一头文件中,加入转换函数的定义:
template
Dest force_cast(Src src)
{
union
{
Dest d;
Src s;
} convertor;
convertor.s = Src;
return convertor.d;
}

template <class T>
struct ClassLoader
{
static HMODULE s_hMod;
};

template <class T>
HMODULE ClassLoader<T>::s_hMod ;
上边的结构是为了为类A的成员函数提供变量动态连接库的据柄,好取出函数指针;
b)

c)在单元文件中加入动态连接库中的类成员函数(包括虚函数和构造函数)的定义,示例如下:
namespace
{
typedef void (A::*PfnConstructorOfA1)();
typedef void (A::*PfnConstructorOfA2)(int);
typedef void (A::*PfnDestructorOfA)();
typedef void (A::*PfnSetNumOfA)(int);
typedef int (A::*PfnGetNumOfA)();
}
A::A()
{
static PfnConstructorOfA1 pfnConsA1 = force_cast<PfnConstructorOfA1>(GetProcAddress(ClassLoader<A>::s_hMod, TEXT("ConstructorOfA0")));

(this->*pfnConsA1)();
}

A::A(int n)
{
static PfnConstructorOfA2 pfnConsA2 = force_cast<PfnConstructorOfA2>(GetProcAddress(ClassLoader<A>::s_hMod, TEXT("ConstructorOfA2")));

(this->*pfnConsA2)(n);
}

void A::SetNum(int n)
{
static PfnSetNumOfA pfnSetNumA = force_cast<PfnSetNumOfA>(GetProcAddress(ClassLoader<A>::s_hMod, TEXT("SetNumOfA")));

(this->*pfnSetNumA)(n);
}

int A::GetNum()
{
static PfnGetNumOfA pfnGetNumA = force_cast<PfnGetNumOfA>(GetProcAddress(ClassLoader<A>::s_hMod, TEXT("GetNumOfA")));

return (this->*pfnGetNumA)();
}

A::~A()
{
static PfnDestructorOfA pfnDestA = force_cast<PfnDestructorOfA>(GetProcAddress(ClassLoader<A>::s_hMod, TEXT("ConstructorOfA0")));

(this->*pfnDestA)();
}
定义了上边的成员函数后,在使用该类时就可以象本地类一样使用了,只是使用前要对ClassLoader<A>::s_hMod进行赋值,让其等于加载的动态连接库据柄;示例如下:
ClassLoader<A>::s_hMod = hMod;
A a2;

a2.SetNum(1);

_tprintf(TEXT("Value of m_nNum in a is %d\n"), a2.GetNum());


A* pA = new A(1);

pA->SetNum(1);

delete pA;
如果在使用时不直接调用成员函数,而是直接动态加载成员函数,那莫上边的函数定义就可以去掉了,动态加载并调用成员函数的示例如下:
typedef void (A::*PfnConstructorOfA1)();
typedef void (A::*PfnConstructorOfA2)(int);
typedef void (A::*PfnDestructorOfA)();
typedef void (A::*PfnSetNumOfA)(int);
typedef int (A::*PfnGetNumOfA)();

A* a1 = (A*)_alloca(sizeof(A));

PfnConstructorOfA1 pfnConsA = force_cast<PfnConstructorOfA1>(GetProcAddress(hMod, TEXT("ConstructorOfA1")));

(a1->*pfnConsA)();

PfnSetNumOfA pfnSetNumA = force_cast<PfnSetNumOfA>(GetProcAddress(hMod, TEXT("SetNumOfA")));

(a1->*pfnSetNumA)(1);

PfnGetNumOfA pfnGetNumA = force_cast<PfnGetNumOfA>(GetProcAddress(hMod, TEXT("GetNumOfA")));

_tprintf(TEXT("Value of m_nNum in a is %d\n"), (a1->*pfnGetNumA)());


PfnDestructorOfA pfnDestA = force_cast<PfnDestructorOfA>(GetProcAddress(hMod, TEXT("DestructorOfA")));

(a1->*pfnDestA)();
当然,为了类调起来方便,最好定义一下成员函数。
w88529593 2008-10-16
  • 打赏
  • 举报
回复
不过不懂得如何把这个发错的帖子删掉
w88529593 2008-10-16
  • 打赏
  • 举报
回复
哦,呵呵,本来是发错了,发到基础里面了,后来感觉不妥,就又往那个VCL里面发了一个
yuanreid 2008-10-16
  • 打赏
  • 举报
回复
为啥要开两个帖子,看来是挺急的啊!
w88529593 2008-10-16
  • 打赏
  • 举报
回复
新建的exe程序是c++ builder的vcl from application.

13,826

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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