怎么在DLL里输出一个含有线程类对象的类呀?

StarLee 2004-06-09 07:15:43
我的类结构如下:
class CMyThread : public CWinThread
{
......
}

class CMyClass
{
private:
CMyThread* m_Thread;
......
public:
Init();//我的初始化函数
......
}

CMyClass::Init()
{
m_Thread=(CMyThread*)AfxBeginThread(RUNTIME_CLASS(CMyThread),THREAD_PRIORITY_NORMAL,0,0);
......
}

我现在要输出CMyClass类,该怎么办呀?应该做成Regular DLL还是Extension DLL呀?我这方面不是很熟悉,请说得详细点!谢谢了,先!
...全文
187 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
bluephenix 2004-06-14
  • 打赏
  • 举报
回复
//Export.h

class CExport
{
public:
.....
virtual BOOL Init() = 0;//我的初始化函数
......

}
/////////////////////
#include "MyThread.h"
class CMyClass : public CExport
{
private:
CMyThread* m_Thread;

public:
......
Init();//我的初始化函数
......
}
//////////////////////////

CMyClass::Init()
{
m_Thread=(CMyThread*)AfxBeginThread(RUNTIME_CLASS(CMyThread),THREAD_PRIORITY_NORMAL,0,0);
......
}

bluephenix 2004-06-14
  • 打赏
  • 举报
回复
太长了 大体上事这样的
1 为没个要导出的类定义一基类 该类中包含导出类中的所有函数(函数全部为纯虚函数
2 导出类继承以上的的基类 并实现各个纯虚函数
3 为没个导出函数设置一个外调函数 用于外部加载DLL时获取该导出类的类指针
4 完了 其他的类该怎么着就怎么着 只有导出的类有以上变化

在调用的时候:
1 将上面所有导出类的基类(那些虚类)的头文件添加到工程中去
2 在需要用到的时候 loadLibrary() 就可以了
bluephenix 2004-06-14
  • 打赏
  • 举报
回复
看看这个 我刚做完一个导出类的东西



This documents intends to give a beginner some knowledge that can be helpfull when designing a project to the Windows plataform. When I start a new project I try to let all the code that seams to be the most changeable in a DLL. This give me the power to change the project having to compile and distribute the minimum piece of code.

But to do this work properly there are some tips that must be followed. Many of you might be asking asking Why not simply use COM ? The answer is that, of course, COM is a great choice in certain situations. However, DLLs are still a very viable alternative as well. Therefore, in this article. I hope to illustrate just when you should use DLLs and exactly how to use them within the framework of an MFC application.


(continued)


A big problem of DLLs (specially those that use MFC) are the debug and release version. These versions are incompatible. You probably had the problem of running the debug application version with the DLL release version. The whole world gets crazy!! The best way, in fact the way Microsoft does, is to give diferent names to the DLLs. So the release DLL stays with the Visual C++ project name and the debug version would look like [Project Name]D.DLL. Using this approach you can send the two DLLs to the system directory and be happy. Those are the steps needed to achieve this (suposing the project name is AAA):

Copy the AAA.def to AAAD.def and change all the AAA to AAAD;
In the Project/Settings, select Win32 Debug
Under the tab Link change the Output file name to AAAD.DLL;
Below in this property page you can see something like:
/def:".\AAA.def" /out:"Debug/AAAD.DLL"
Change to:
/def:".\AAAD.def" /out:"Debug/AAAD.DLL"


Now the the debug version will create AAAD.lib and AAAD.DLL files. When I create a DLL I create an include header to it (I think everybody does), which I named DLL header. This header has all the exported classes definitions. And to be more efficient I include the linking stuff in it, so to use the DLL you doesnt have to add the lib file to the Project Settings. My header looks like:


#ifndef DEF_MUDASDASDASDASDAS
#define DEF_MUDASDASDASDASDAS

#ifdef _DEBUG
#pragma comment(lib, AAAD.lib)
#else
#pragma comment(lib, AAA.lib)
#endif

//... the classes definitions goes here

#endif //MUDASDASDASDASDAS

Programming for Changes
The prefered kind of DLL used to export classes are the MFC extension DLLs. By using this you can easily instanciate a classe that is within a DLL. To do this you just declare the class like this:

class AFX_EXT_CLASS CFoo
{
//...
}

In the application that uses this class you just include the DLL header and everything is cool. The problem is: everytime you need to include a member variable or a method to an exported class you have to change the DLL header, which means recompile all those who use the DLL. To new methods I dont know a way to overcome this recompilation, but for new variables theres a way.

Instead of declaring the member variables directly to the class body, you create a kind of implementation class, like the sample code:

class CFooImpl;
class CFoo
{
protected:
CFooImpl* m_pThis;
};

So the CFooImpl class doesnt need to be declare to those how use this DLL. The implementation of CFoo would look like:

class CFooImpl
{
public:
CString m_sName;
};

CFoo::CFoo()
{
m_pThis = new CFooImpl;

m_pThis->m_sName = _T("Unknown");
}

CFoo::~CFoo()
{
delete m_pThis;
}

Another method to be prepared for changes is to use inteligents structs the way the Windows API does. So you declare a method that has an LPVOID as in and out parameter. Those pointers are address of structs instances. The trick is to define as the first struct member a DWORD regardings its size. This way you know which data is expected.


typedef struct tagCHANGEABLE
{
DWORD dwSize;
long lBytes;
}CHANGEABLE, *LPCHANGEABLE;

BOOL CFoo::Method(LPVOID lpIn)
{
LPCHANGEABLE lpChangeable = (LPCHANGEABLE)lpIn;

if (lpChangeable->dwSize == sizeof(CHANGEABLE))
{
//...
return TRUE;
}

return FALSE;
}


Using it:

CFoo myFoo;

CHANGEABLE changeable;
memset(&changeable, 0, sizeof(changeable));

changeable.dwSize = sizeof(changeable);

myFoo.Method(&changeable);

DLL Loaded When Needed
Sometimes you have uncommon situations that you need to call a dialog or create a class instance. So you decide to put those in a DLL, but you dont want it to be loaded when the application gets executed. You want to load the DLL when needed (COM). This kind of DLL I call Dynamic DLL (stupid name I know Dynamic Dynamic link libraries). So you declare the exported function as:

__declspec( DLLexport )
void MyExportedFunc(DWORD dw)
{
//...
}

We need to include this function in the defs files (debug and release). The debug def file would look like this:

; AAAD.def : Declares the module parameters for the DLL.

LIBRARY "AAAD"

DESCRIPTION 'AAAD Windows Dynamic Link Library'

EXPORTS
MyExportedFunc @1
; Explicit exports can go here

Now to use this function we need to load the library, find the function entry point and call it.

typedef void (*MYFUNC)(DWORD);

#ifdef _DEBUG
HINSTANCE hDLL = AfxLoadLibrary("AAADLLD");
#else
HINSTANCE hDLL = AfxLoadLibrary("AAADLL");
#endif

if (hDLL)
{
FARPROC pnProc = GetProcAddress(hDLL, "MyExportedFunc");
MYFUNC pnMyfunc = (MYFUNC)pnProc;

pnMyfunc(0);

FreeLibrary(hDLL);
}

Remember that to use show a dialog you must take care of the resource stuffs (AfxSetResource..). You can use this approach to create class instances. The class definition must use pure virtual functions (to avoid unresolved external symbol). It is just like COM.

The class definition should look like this:

class CFoo
{
public:
virtual void Initialize (CString sName) = 0;
};

You implement this "interface" with another class that is not visible through the DLL header file.

class CFooImp : public CFoo
{
public:
CFooImp();
virtual ~CFooImp();

void Initialize (CString sName)
{
m_sName = sName;
}

protected:
CString m_sName;
};

To create an instance of this class (interface) you create an exported function.

__declspec(DLLexport)

CFoo* CreateFoo(DWORD dwVersion)
{
if (dwVersion == CURRENT_VERSION)
return new CFooImp;

return NULL;
}

The application creates the class instance like this:

typedef CFoo* (*MYFUNC)(DWORD);

#ifdef _DEBUG
HINSTANCE hDLL = AfxLoadLibrary("AAADLLD");
#else
HINSTANCE hDLL = AfxLoadLibrary("AAADLL");
#endif

if (hDLL)
{
FARPROC pnProc = GetProcAddress(hDLL, " CreateFoo");
MYFUNC pnMyfunc = (MYFUNC)pnProc;

CFoo* pFoo = pnMyfunc(0);

pFoo->Initialize(_T("Hi"));

delete pFoo;

FreeLibrary(hDLL);
}

Remember that you cannot free the library until you deleted the CFoo instance.

Conclusion
These examples explained the powers of well designed DLLs. But if the whole project has a bad design no miracle will make your applications easy to change and update. The good design is the first and most important step to the successfull project.


StarLee 2004-06-13
  • 打赏
  • 举报
回复
我做好了DLL,在调用的时候是生明一个DLL输出类的对象为Dialog的成员,在Debug编译和运行都没有问题,但是在Release编译时出现如下错误,这是为什么呀?
DLLTest.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall CMyClass::~CMyClass(void)" (__imp_??1CMyClass@@UAE@XZ)

DLLTestDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall CMyClass::~CMyClass(void)" (__imp_??1CMyClass@@UAE@XZ)

DLLTestDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall CMyClass::CMyClass(void)" (__imp_??0CMyClass@@QAE@XZ)

DLLTestDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: bool __thiscall CMyClass::Init(void)" (__imp_?Init@CMyClass@@QAE@XZ)
StarLee 2004-06-13
  • 打赏
  • 举报
回复
我做好了DLL,在调用的时候是生明一个DLL输出类的对为问什么呀?
DLLTest.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall CMyClass::~CMyClass(void)" (__imp_??1CMyClass@@UAE@XZ)

DLLTestDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall CMyClass::~CMyClass(void)" (__imp_??1CMyClass@@UAE@XZ)

DLLTestDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall CMyClass::CMyClass(void)" (__imp_??0CMyClass@@QAE@XZ)

DLLTestDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: bool __thiscall CMyClass::Init(void)" (__imp_?Init@CMyClass@@QAE@XZ)
wangzi163 2004-06-10
  • 打赏
  • 举报
回复
extern "C" __declspec(dllexport) class MyClass{...}
StarLee 2004-06-10
  • 打赏
  • 举报
回复
请高手们说得再清楚些!
最好有例子!
谢谢了,先!
kundy 2004-06-09
  • 打赏
  • 举报
回复
请参考:

MFC 扩展 DLL 是通常实现从现有 Microsoft 基础类库类派生的可重用类的 DLL。扩展 DLL 是使用 MFC 动态链接库版本(也称作共享 MFC 版本)生成的。只有用共享 MFC 版本生成的 MFC 可执行文件(应用程序或规则 DLL)才能使用扩展 DLL。使用扩展 DLL,可以从 MFC 派生新的自定义类,然后将此“扩展”版本的 MFC 提供给调用 DLL 的应用程序。

扩展 DLL 也可用于在应用程序和 DLL 之间传递 MFC 派生的对象。与已传递的对象关联的成员函数存在于创建对象所在的模块中。由于在使用 MFC 的共享 DLL 版本时正确导出了这些函数,因此可以在应用程序和它加载的扩展 DLL 之间随意传递 MFC 或 MFC 派生的对象指针。

enoloo 2004-06-09
  • 打赏
  • 举报
回复
就输出类贝。
paladinsong 2004-06-09
  • 打赏
  • 举报
回复
这跟你做成Regular DLL还是Extension DLL无关,这两个主要是看你要把程序怎么发布,做成Regular的话会把mfc里面的库给链接到你的dll里面去,而Externsion则不会。
怎么写,不就是一个extern "C" __declspec(dllexport) class MyClass{...}了
赖勇浩 2004-06-09
  • 打赏
  • 举报
回复
我不会,,,所以特别关注,帮顶,接分.
zhangnanonnet 2004-06-09
  • 打赏
  • 举报
回复
把它作为指针传出来啊。。。你忘了void *这个东西的妙用了吗,任何类型的指针都可以作为void *类型参数传递的阿
kundy 2004-06-09
  • 打赏
  • 举报
回复
应该是Extension DLL,可以看看msdn

一起学习 ^_^

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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