使用DEF文件无法导出函数,请高手指点。

massice 2010-08-04 10:41:45
目前正在看COM技术内幕第5章,根据书中的代码想自己试试。
结果发现无法从生成的DLL中找到指定的CreateInstance函数,请问这是怎么回事?是不是DLL中根本就没有导出CreateInstance呢?


CMPNET1.CPP

//文件前边内容略。
//
// Creation function
//
extern "C" IUnknown* CreateInstance()
{
IUnknown* pI = static_cast<IX*>(new CA) ;
pI->AddRef() ;
return pI ;
}


CMPNET1.DEF

;
; Cmpnt1 module-definition file
;

LIBRARY CMPNT1.dll
DESCRIPTION '(c)1996-1997 Dale E. Rogerson'

EXPORTS
CreateInstance @1 PRIVATE



CLIENT1.CPP

typedef IUnknown* (*CREATEFUNCPTR)() ;

IUnknown* CallCreateInstance(char* name)
{
// Load dynamic link library into process.
HINSTANCE hComponent = LoadLibrary(name) ;
if (hComponent == NULL)
{
cout << "CallCreateInstance:\tError: Cannot load component." << endl ;
return NULL ;
}

// Get address for CreateInstance function.
CREATEFUNCPTR CreateInstance
= (CREATEFUNCPTR)::GetProcAddress(hComponent, "CreateInstance") ;
if (CreateInstance == NULL)
{
cout << "CallCreateInstance:\tError: " //运行时直接代码走到这里,找不到函数
<< "Cannot find CreateInstance function."
<< endl ;
return NULL ;
}

return CreateInstance() ;
}









...全文
516 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
jerjupiter 2011-02-12
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 massice 的回复:]
上边贴的代码是我从网上下载的书中代码。
我自己又重新写了一个简单的动态库,又自己写了一个加载动态库的工程,
结果使用DEF文件生成的MyDEFDLL.dll,导出两个函数(MyDefFun和MyVOIDFun)
使用dependency walker查看也可以查看到导出两个函数,见下图


然后加载MyDEFDLL.dll,就可以得到MyDefFun和MyVOIDFun,程序没有问题,……
[/Quote]

你这个代码判断有误啊。
if (NULL == hInst)
{
std::cout << "error." << std::endl; //代码没有走到这
return -1;
}
这里应该判断 NULL == CreateInstance 才对啊。
massice 2010-08-06
  • 打赏
  • 举报
回复
上边贴的代码是我从网上下载的书中代码。
我自己又重新写了一个简单的动态库,又自己写了一个加载动态库的工程,
结果使用DEF文件生成的MyDEFDLL.dll,导出两个函数(MyDefFun和MyVOIDFun)
使用dependency walker查看也可以查看到导出两个函数,见下图


然后加载MyDEFDLL.dll,就可以得到MyDefFun和MyVOIDFun,程序没有问题,正常执行。
然后我修改代码,加载书中代码生成的CMPNT1.DLL,结果可以查找到CreateInstance函数,
我就奇怪了,我写的加载动态库代码和书中例子几本上一样啊,为何书中的代码却不好用呢。


HINSTANCE hInst = NULL;
//test
hInst = LoadLibrary("..\\lib\\CMPNT1.dll");
if (NULL == hInst)
{
std::cout << "error." << std::endl;
return -1;
}
typedef IUnknown* (*CREATEFUNCPTR)() ;
CREATEFUNCPTR CreateInstance = (CREATEFUNCPTR)::GetProcAddress(hInst, "CreateInstance") ;
if (NULL == hInst)
{
std::cout << "error." << std::endl; //代码没有走到这
return -1;
}
//代码走到这,说明找到了CreateInstance函数了。
cout << "success" << endl;
return 0;


massice 2010-08-06
  • 打赏
  • 举报
回复
呵呵,谢谢你的关注。感谢指导!
以前没有使用过DEF导出函数,这回正好测试了,经验还是很宝贵的。
好了,结贴啦!
cranium 2010-08-06
  • 打赏
  • 举报
回复
或许吧。

我上面还在猜测是不是你没把正确DLL拷贝到EXE目录呢~

massice 2010-08-06
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 cranium 的回复:]
C/C++ code
// Load dynamic link library into process.
HINSTANCE hComponent = LoadLibrary(name) ;
if (hComponent == NULL)
{
cout << "CallCreateInstance:\tError: Cannot load……
[/Quote]

神奇了。。。。。
我重新创建了一个新的client工程,把原来的client文件直接拷贝过来,将最新的CMPNT1.DLL拷贝放到client的EXE的目录,再次加载DLL,结果OK了。
汗一个,难道是我之前搞来搞去把环境给搞乱了?
xengine-qyt 2010-08-06
  • 打赏
  • 举报
回复
饿 我以前遇到过 函数导出 调用出错,那是因为使用了新函数 才会这样。

函数导不出到没遇到过!
蜥蜴枪王 2010-08-06
  • 打赏
  • 举报
回复
LIBRARY CMPNT1.dll

看起来 def的定义是没什么问题的,会不会是你加载dll的路径错了?

LIBRARY CMPNET1.dll
cranium 2010-08-06
  • 打赏
  • 举报
回复
    // Load dynamic link library into process.
HINSTANCE hComponent = LoadLibrary(name) ;
if (hComponent == NULL)
{
cout << "CallCreateInstance:\tError: Cannot load component." << endl ;
return NULL ;
}

把原程序里LoadLibrary(name) 的参数name换成实际的dll名字字符串看看,就像你在新的工程里做的那样。

可能是加载了错误的DLL吧。还是该检查下 CallCreateInstance(char* name)函数的调用,传入的参数是否是你新生成DLL的路径,如果参数只是COMP1.dll的话,可能首先加载的是CLIENT程序目录下的DLL,而不是你新生成的。你确定有把新生成的DLL拷贝至CLIENT工作目录下么?
massice 2010-08-06
  • 打赏
  • 举报
回复
返回的错误时127,使用Error Lookup查询为
Status: Failure Code:127
Facility: Windows(Non COM)
找不到指定的程序。

最开始我以为是我使用DEF文件导出函数可能出现问题,按目前的进展来看,函数肯定已经导出了,应该是之前的client工程可能有问题。
cranium 2010-08-06
  • 打赏
  • 举报
回复
呵呵,猜你肯定郁闷的很~

还是看看原先错误代码的LastError错误号是多少?

还有对比下工程配置属性。新建个空的项目,直接将原先的源文件添加到新项目里编译。
必要的话,把源文件里的LoadLibrary的参数也改成直接指定路径的看了。说不定它原先链接的不是你新编译好的DLL呢!
cranium 2010-08-05
  • 打赏
  • 举报
回复
你是否用dependency walker工具或类似工具查看了你编译出的DLL,确定无任何导出函数?
(你是如何确定没有导出函数的?)
横云断岭 2010-08-05
  • 打赏
  • 举报
回复
貌似要在工程的属性中指定def文件。LZ可以去看下。
stilling2006 2010-08-05
  • 打赏
  • 举报
回复
我也遇见过,后来忘了怎么解决的。记得是看到孙鑫的那本什么MFC的书解决的。
cranium 2010-08-05
  • 打赏
  • 举报
回复
可以看到你的图,看来确实是已经正确的将函数导出了。

你可以试着在GetProcAddress调用后的错误处理里立即调用GetLastError查看详细错误信息(取得GetLastError的返回值后也可以简单的放入Error lookup实用工具里直接查看CODE信息,当然你也可以在代码里调用API取得,不过麻烦点)。或许可以帮助你找到错误所在。

除此之外,你也可以尝试将GetProcAddress第二个参数换成 (LPCSTR)1 ,以导出函数的编号形式调用,看看这种方式是否奏效。
massice 2010-08-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 cranium 的回复:]
设置 :工程属性-->linker--->input---->Module Definition File

如果你是直接在工程中右键,添加new item的方式添加def文件,那么这个选项是自动被设置的。
[/Quote]

已经在工程属性-》连接器-》输入->模块定义文件中指定了 CMPNT1.DEF了,但是重新编译出的DLL还是没有将函数导出了。
请问这是怎么回事呢?
huhacn 2010-08-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 cranium 的回复:]
设置 :工程属性-->linker--->input---->Module Definition File

如果你是直接在工程中右键,添加new item的方式添加def文件,那么这个选项是自动被设置的。
[/Quote]
是的
ayw215 2010-08-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 cranium 的回复:]

设置 :工程属性-->linker--->input---->Module Definition File

如果你是直接在工程中右键,添加new item的方式添加def文件,那么这个选项是自动被设置的。
[/Quote]
up
zh848024897 2010-08-05
  • 打赏
  • 举报
回复
学习学习
massice 2010-08-05
  • 打赏
  • 举报
回复


用dependency walker 查看好像是导出了,不知道能不能看到图片。
如果是导出了为啥不好用呢?
cranium 2010-08-05
  • 打赏
  • 举报
回复
我的意思是你去查查看,仅告诉我你没查是没什么帮助的。
加载更多回复(2)

64,682

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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