您的位置:首页 > 其它

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,

如果是这样,问题能马上就发现.



不知道好习惯,是不是都是碰壁得来的...



回来做了个实验, 验证了这个问题.

函数的形参是由函数实现的形参决定的, 和导出函数头声明无关. 但是也能编译的过去,很怪的.

//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)
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐