DLL函数定义和函数实现写函数类型的不同, 引起不能使用Dll中的函数
2011-01-12 21:14
453 查看
<2011_0112>
/**
* 这个.h是给Dll的导出函数的头文件
*/
MY_DLL_API int __stdcall DoSomething(INT &nLen);
/**
* 实现文件
*/
MY_DLL_API int __stdcall DoSomething(DWORD &nLen)
{
//...
return S_OK;
}
/**
* def文件
*/
LIBRARY "xxlib"
DESCRIPTION 'xxLib Windows Dynamic Link Library'
EXPORTS
DoSomething
编译不报错, 等用到DoSomething函数时, 总是提示无法解决的外部函数.
工程中的函数名字起的比较长, 30几个字符长度. 入参4个, 这个写错的入参在最后一个.
自己折磨自己,花了5个小时来解决这个问题.
总结: 标准win32Dll, 导出的是内建类型. 都是全局函数, 编译时, 并不需要导出函数的头文件.
那个头文件是给调用者配合.lib一起使用的, 要是不用.h,和.lib, 就得动态调用.
还有一点,入参名称起名不好,引起的问题真不小. 要是原先是INT &nLen, 当长度不够,需要改变时, 应写成DWORD &dwLen,
如果是这样,问题能马上就发现.
不知道好习惯,是不是都是碰壁得来的...
回来做了个实验, 验证了这个问题.
函数的形参是由函数实现的形参决定的, 和导出函数头声明无关. 但是也能编译的过去,很怪的.
/**
* 这个.h是给Dll的导出函数的头文件
*/
MY_DLL_API int __stdcall DoSomething(INT &nLen);
/**
* 实现文件
*/
MY_DLL_API int __stdcall DoSomething(DWORD &nLen)
{
//...
return S_OK;
}
/**
* def文件
*/
LIBRARY "xxlib"
DESCRIPTION 'xxLib Windows Dynamic Link Library'
EXPORTS
DoSomething
编译不报错, 等用到DoSomething函数时, 总是提示无法解决的外部函数.
工程中的函数名字起的比较长, 30几个字符长度. 入参4个, 这个写错的入参在最后一个.
自己折磨自己,花了5个小时来解决这个问题.
总结: 标准win32Dll, 导出的是内建类型. 都是全局函数, 编译时, 并不需要导出函数的头文件.
那个头文件是给调用者配合.lib一起使用的, 要是不用.h,和.lib, 就得动态调用.
还有一点,入参名称起名不好,引起的问题真不小. 要是原先是INT &nLen, 当长度不够,需要改变时, 应写成DWORD &dwLen,
如果是这样,问题能马上就发现.
不知道好习惯,是不是都是碰壁得来的...
回来做了个实验, 验证了这个问题.
函数的形参是由函数实现的形参决定的, 和导出函数头声明无关. 但是也能编译的过去,很怪的.
//MfcStdDllFrame_Export.h //MFCSTDDLLFRAME_EXPORT_H #ifndef MFCSTDDLLFRAME_EXPORT_H #define MFCSTDDLLFRAME_EXPORT_H #ifdef MFCSTDDLLFRAME_EXPORT #define MFCSTDDLLFRAME_API __declspec(dllexport) #else #define MFCSTDDLLFRAME_API __declspec(dllimport) #endif MFCSTDDLLFRAME_API int __stdcall test(INT & nLen); #endif
// MfcStdDllFrame.cpp : Defines the initialization routines for the DLL. // #include "stdafx.h" #include "MfcStdDllFrame.h" #include "MfcStdDllFrame_Export.h" /** * 1. test 原来在 MfcStdDllFrame_Export.h 中定义 * 和实现文件的入参不同 * 现在搬到实现文件中来, 居然也不报错. * 2. 在MfcStdDllFrame_Export.h中, 也声明 MFCSTDDLLFRAME_API int __stdcall test(INT & nLen); * 也能编译的过. * 不知道编译器怎么解释的? */ MFCSTDDLLFRAME_API int __stdcall test(INT & nLen); MFCSTDDLLFRAME_API int __stdcall test(DWORD & nLen) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); return S_OK; } #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif BEGIN_MESSAGE_MAP(CMfcStdDllFrameApp, CWinApp) //{{AFX_MSG_MAP(CMfcStdDllFrameApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMfcStdDllFrameApp construction CMfcStdDllFrameApp::CMfcStdDllFrameApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } ///////////////////////////////////////////////////////////////////////////// // The one and only CMfcStdDllFrameApp object CMfcStdDllFrameApp theApp;
; MfcStdDllFrame.def : Declares the module parameters for the DLL. LIBRARY "MfcStdDllFrame" DESCRIPTION 'MfcStdDllFrame Windows Dynamic Link Library' EXPORTS ; Explicit exports can go here test
// testDll.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "testDll.h" /** * 如果到调用已有Dll的时候,再自己改头文件声明,就没用了. * 用dumpbin来看Dll中的导出函数, 能看到函数名称, 看不到形参列表 */ //#include "MfcStdDllFrame_Export.h" /** * DLL生成时, 已经按照实现文件定义的形参生成了 MFCSTDDLLFRAME_API int __stdcall test(DWORD & nLen) * * 调用时, 如果声明成MFCSTDDLLFRAME_API int __stdcall test(INT & nLen); * 编译不过, error LNK2001: unresolved external symbol "int __stdcall test(int &)" (?test@@YGHAAH@Z) * * * */ #define MFCSTDDLLFRAME_API __declspec(dllexport) MFCSTDDLLFRAME_API int __stdcall test(DWORD & nLen); #pragma comment(lib, "MfcStdDllFrame.lib") #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // The one and only application object CWinApp theApp; using namespace std; int fnTestDll(); int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; // initialize MFC and print and error on failure if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs cerr << _T("Fatal Error: MFC initialization failed") << endl; nRetCode = 1; } else { // TODO: code your application's behavior here. CString strHello; strHello.LoadString(IDS_HELLO); cout << (LPCTSTR)strHello << endl; fnTestDll(); } return nRetCode; } int fnTestDll() { //INT nParam = 0; DWORD nParam = 0; //看来函数定义的形参名称起的不好, 存在的隐患还埋的很深 return test(nParam);//编译错误在这 } /** * 编译结果 * Linking... * testDll.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) int __stdcall test(int &)" (__imp_?test@@YGHAAH@Z) * Debug/testDll.exe : fatal error LNK1120: 1 unresolved externals * * 如果按照导出函数的实际实现的函数定义来声明, 必须是编译DLL时,就和函数实现的入参相同 * 就可以编译通过 * * rem dumpbin /ALL ./MfcStdDllFrame.dll > ./dumpbin_out.txt * dumpbin /EXPORTS ./MfcStdDllFrame.dll * * MFCSTDDLLFRAME_API int __stdcall test(DWORD & nLen) */
相关文章推荐
- C++中函数定义返回类型和内部实现返回类型不同的原因
- C++中函数定义返回类型和内部实现返回类型不同的原因
- 编写一个函数reverse_string(char * string)(递归实现)实现:将参数字符串中的字符反向排列。要求:不能使用C函数库中的字符串操作函数。
- 深入浅出Dll( 函数导出、类导出、钓子dll、不同语言混合编程方法、插件等的实现方法)
- 使用泛型实现类型转化-使用通配符上限下限区分协变和逆变采取不同的转化方式
- 从 windows 到 linux(1):g++不能用函数内定义的类型做模板参数
- 使用回调函数实现一个通用的冒泡排序,可以排序不同的数据类型。
- MFC dll 类型是 共享 规则 导出对话框函数使用出错解决办法
- Effective Modern C++ 条款22 当使用Pimpl Idiom时,在实现文件中定义特殊成员函数
- C++静态库中使用_declspec(dllexport) 不能导出函数的问题
- 用最简单的函数实现功能:判断一个int数据是否是2的x次幂(不能使用循环)。
- 深入浅出Dll(介绍函数导出、类导出、钓子dll、不同语言混合编程方法、插件等的实现方法)
- 使用@RequestMapping 定义处理器函数-支持的函数返回类型
- 多次包含同一个头文件,实现只写一句宏定义就可以定义出两个不同类型的变量
- php实现的统计字数函数定义与使用示例
- python 函数定义和内置函数isinstance以及数据类型检查type的使用
- C语言学习6 :指针的定义,指针类型要合法,指针要初始化,指针做函数参数,数组和指针的通用性,指针+1所代表的空间,void * 指针,交换函数中的指针,数组和字符型指针区别,字符型指针的应用,使用指针完成字符操作函数
- 实现C语言的拷贝函数且将复制后的字符串逆序,不能使用库函数,不能定义其他的变量。
- DLL导出函数使用wchar_t类型的问题
- 使用json来定义函数,在里面可以定义多个函数的实现方法