导出类里有static成员怎么处理?(DECLARE_DYNCREATE)

devinside 2008-08-18 06:02:06
声明为DYNCREATE的类导出后连接提示错误,static成员CRuntimeClass什么什么的没找到,又随便试了一个其他的static变量,导出后一旦使用则连接出错,请问该如何处理
...全文
465 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
robustwell 2010-12-29
  • 打赏
  • 举报
回复
AFX_EXT_CLASS ffff
devinside 2008-09-03
  • 打赏
  • 举报
回复
再跟一贴免得以后忘了,来源:
http://msdn.microsoft.com/zh-cn/library/9xyb5w93(VS.80).aspx

使用 AFX_EXT_CLASS 导出和导入

扩展 DLL 使用 AFX_EXT_CLASS 宏导出类;链接到扩展 DLL 的可执行文件使用该宏导入类。用于生成扩展 DLL 的相同头文件可通过 AFX_EXT_CLASS 宏与链接到 DLL 的可执行文件一起使用。

在 DLL 的头文件中,将 AFX_EXT_CLASS 关键字添加到类的声明中,如下所示:

复制代码
class AFX_EXT_CLASS CMyClass : public CDocument
{
// <body of class>
};当定义了预处理器符号 _AFXDLL 和 _AFXEXT 时,该宏被 MFC 定义为 __declspec(dllexport)。但当定义了 _AFXDLL 而未定义 _AFXEXT 时,该宏被定义为 __declspec(dllimport)。定义后,预处理器符号 _AFXDLL 指示共享 MFC 版本正在由目标可执行文件(DLL 或应用程序)使用。当 _AFXDLL 和 _AFXEXT 都定义了时,这指示目标可执行文件是扩展 DLL。

由于从扩展 DLL 导出时,AFX_EXT_CLASS 被定义为 __declspec(dllexport),因此可以导出整个类,而不必将该类的所有符号的修饰名放到 .def 文件中。此方法由 MFC 示例 DLLHUSK 使用。

虽然使用此方法可以避免创建 .def 文件和类的所有修饰名,但由于名称可以按序号导出,因此创建 .def 文件的效率更高。若要使用 .def 文件导出方法,请将下列代码放在头文件的开头和结尾处:

复制代码
#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
// <body of your header file>
#undef AFX_DATA
#define AFX_DATA警告
导出内联函数时要小心,因为它们有可能导致版本冲突。内联函数扩展到应用程序代码中;因此,如果以后重写内联函数,除非重新编译应用程序本身,否则内联函数不会被更新。通常,不用重新生成使用 DLL 函数的应用程序就可以更新 DLL 函数。


导出类中的个别成员
有时,您可能希望导出类中的个别成员。例如,如果导出 CDialog 派生类,可能只需要导出构造函数和 DoModal 调用。可以对需要导出的个别成员使用 AFX_EXT_CLASS。

例如:

复制代码
class CExampleDialog : public CDialog
{
public:
AFX_EXT_CLASS CExampleDialog();
AFX_EXT_CLASS int DoModal();
...
// rest of class definition
...
};您不再导出类的所有成员,但由于 MFC 宏的工作方式,您可能会遇到其他问题。几个 MFC 的 Helper 宏实际声明或定义数据成员。因此,还必须从 DLL 导出这些数据成员。

例如,当生成扩展 DLL 时,DECLARE_DYNAMIC 宏的定义如下:

复制代码
#define DECLARE_DYNAMIC(class_name) \
protected: \
static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
static AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \以 static AFX_DATA 打头的行声明类的内部静态对象。若要正确导出该类并从客户端可执行文件访问运行时信息,必须导出此静态对象。由于静态对象是用 AFX_DATA 修饰符声明的,因此只需在生成 DLL 时将 AFX_DATA 定义为 __declspec(dllexport),并在生成客户端可执行文件时将 AFX_DATA 定义为 __declspec(dllimport)。由于已经以此方式定义了 AFX_EXT_CLASS,因此只需参考类定义,将 AFX_DATA 重定义为与 AFX_EXT_CLASS 相同。

例如:

复制代码
#undef AFX_DATA
#define AFX_DATA AFX_EXT_CLASS

class CExampleView : public CView
{
DECLARE_DYNAMIC()
// ... class definition ...
};

#undef AFX_DATA
#define AFX_DATAMFC 总是在其宏的内部定义的数据项上使用 AFX_DATA 符号,因此此技术适用于所有这类情况。例如,它适用于 DECLARE_MESSAGE_MAP。

注意
如果导出整个类而非选定的类成员,静态数据成员将自动导出。

devinside 2008-09-03
  • 打赏
  • 举报
回复
晕死了,如梦方醒啊,多谢楼上的啊
vcPlayer 2008-09-02
  • 打赏
  • 举报
回复
请用宏:AFX_EXT_CLASS 替换你的__declspec ( dllexport )

你使用的工程应该变为__declspec ( dllimport )。是这个原因造成的。另外,使用的工程不要再用以下语句:

int ClassA::a = 0 ;
IMPLEMENT_DYNCREATE ( ClassA , CObject )
IMPLEMENT_DYNCREATE ( ClassB , ClassA )
devinside 2008-09-02
  • 打赏
  • 举报
回复
再up一次,周五结贴
devinside 2008-08-28
  • 打赏
  • 举报
回复
工程类型:MfcAppWizard(Dll)
名称:MfcDll
DLL类型:MFCExtensionDLL
新建文件:NewClass.h放到HeaderFiles下,内容
class __declspec ( dllexport ) ClassA : public CObject
{
DECLARE_DYNCREATE ( ClassA )
public :
static int a ;
ClassA () {} ;
ClassA ( CString sz ) { szA = sz ; }
void Show () { AfxMessageBox ( szA ) ; }
CString szA ;
};

class __declspec ( dllexport ) ClassB : public ClassA
{
DECLARE_DYNCREATE ( ClassB )
public:
ClassB () {} ;
ClassB ( CString sz ) { szA = sz ; }
};

在MfcDll.cpp最后添加如下代码

#include "NewClass.h"

int ClassA::a = 1 ;
IMPLEMENT_DYNCREATE ( ClassA , CObject )
IMPLEMENT_DYNCREATE ( ClassB , ClassA )


然后再新建一个工程
类型:MfcAppWizard(exe)
名称:MfcTest
勾上Add to current workspace
类型:Dialogbased
加个按钮,响应函数OnButton1改成
#include "../NewClass.h"

int ClassA::a = 0 ;
IMPLEMENT_DYNCREATE ( ClassA , CObject )
IMPLEMENT_DYNCREATE ( ClassB , ClassA )

void CMfcTestDlg::OnButton1()
{
// TODO: Add your control notification handler code here
ClassB a ( "ADSF" ) ;
a.Show () ;
int xx = ClassA::a ;
if ( a.IsKindOf ( RUNTIME_CLASS ( ClassA ) ) && a.IsKindOf ( RUNTIME_CLASS ( ClassB ) ) )
int fff = 1 ;
}

然后把俩工程清一下改工程设置
MfcDll工程把debug/general/output由Debug/MfcDll.dll改为MfcTest/Debug/MfcDll.dll
MfcTest公差把debug/input/Ojb.LibModules添加MfcTest/Debug/MfcDll.dll
完了,先编译MfcDll再编译MfcTest运行吧

如果去掉了MfcTest工程里面的三处对静态变量的处理就出现连接错误:
Creating library Debug/MfcTest.lib and object Debug/MfcTest.exp
MfcTestDlg.obj : error LNK2001: unresolved external symbol "public: static struct CRuntimeClass const ClassB::classClassB" (?classClassB@ClassB@@2UCRuntimeClass@@B)
MfcTestDlg.obj : error LNK2001: unresolved external symbol "public: static struct CRuntimeClass const ClassA::classClassA" (?classClassA@ClassA@@2UCRuntimeClass@@B)
MfcTestDlg.obj : error LNK2001: unresolved external symbol "public: static int ClassA::a" (?a@ClassA@@2HA)
Debug/MfcTest.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.

MfcTest.exe - 4 error(s), 0 warning(s)

楼上的哪位大侠有时间看看小弟做法错在哪里
devinside 2008-08-27
  • 打赏
  • 举报
回复
画蛇添足?的确看着象,但不写试试,能编译过去才行
vcPlayer 2008-08-27
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 devinside 的回复:]
画蛇添足?的确看着象,但不写试试,能编译过去才行
[/Quote]


// 外部工程使用导出类:
//
// 你确保你的导出类在DLL中与外部工程中的定义一致?
//
// 你确保你把DLL的LIB文件引入到你的工程了吗?
//
// 不写怎么编译不过去?报什么错误?????
vcPlayer 2008-08-26
  • 打赏
  • 举报
回复
IMPLEMENT_DYNCREATE ( ClassA , CObject )
IMPLEMENT_DYNCREATE ( ClassB , ClassA )

外部调用文件中的这两句拿来干嘛?画蛇添足。
devinside 2008-08-26
  • 打赏
  • 举报
回复
不行,orbit的方法没用啊,在外面调用一样没定义
devinside 2008-08-24
  • 打赏
  • 举报
回复
楼上的方法我好像试过,不管用的吧,明天上班再去试试
导入是在工程中引用的lib吧,有点儿忘了,要么就是用的progma comment,就知道这么两个方法
即使楼上的方法可行那IMPLEMENT又怎么办呢,把宏定义重写是不是没定义的啊
吹泡泡的小猫 2008-08-21
  • 打赏
  • 举报
回复
在你的NewClass.cpp文件中这样定义a:

__declspec ( dllexport ) int ClassA::a = 0 ;

就不用在其它地方再定义了
菜牛 2008-08-21
  • 打赏
  • 举报
回复
你是怎么导入的?
devinside 2008-08-19
  • 打赏
  • 举报
回复
// NewClass.h
class __declspec ( dllexport ) ClassA : public CObject
{
DECLARE_DYNCREATE ( ClassA )
public :
static int a ;
ClassA () {} ;
ClassA ( CString sz ) { szA = sz ; }
void Show () { AfxMessageBox ( szA ) ; }
CString szA ;
};

class __declspec ( dllexport ) ClassB : public ClassA
{
DECLARE_DYNCREATE ( ClassB )
public:
ClassB () {} ;
ClassB ( CString sz ) { szA = sz ; }
};
//NewClass.cpp

IMPLEMENT_DYNCREATE ( ClassA , CObject )
IMPLEMENT_DYNCREATE ( ClassB , ClassA )

//外部调用

#include "../NewClass.h"

int ClassA::a = 0 ;
IMPLEMENT_DYNCREATE ( ClassA , CObject )
IMPLEMENT_DYNCREATE ( ClassB , ClassA )

void CMfcTestDlg::OnButton1()
{
// TODO: Add your control notification handler code here
ClassB a ( "ADSF" ) ;
a.Show () ;
int xx = ClassA::a ;
if ( a.IsKindOf ( RUNTIME_CLASS ( ClassA ) ) && a.IsKindOf ( RUNTIME_CLASS ( ClassB ) ) )
int fff = 1 ;
}

经楼上提示发现只有按上面的写法才能连接通过,就是static要再引用dll的地方也写一边,IMPLEMENT也要写两边,但dll和非dll的IMPLEMENT定义不一样啊,这样写可行吗??
devinside 2008-08-19
  • 打赏
  • 举报
回复
请问楼上什么意思,我可不是没写int C::i啊,不如非dll也会出错的...
devinside 2008-08-19
  • 打赏
  • 举报
回复
这板没人看吗,连续三次了,路过的帮顶一下
cnzdgs 2008-08-18
  • 打赏
  • 举报
回复
静态变量需要单独分配空间。例如:
class c
{
public:
static int i;
};
int c::i;

15,471

社区成员

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

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