C#如何调用C++写的传统dll中的函数?

hahahawk 2003-04-10 04:13:00
我用c++写的一个a.dll,其中:
int foo()
{
int a;
......
return a;
}
为什么用C#如下调用时候出错?
[DllImport("a.dll",EntryPoint="foo")]
extern static int foo();
......
int ret = foo();
运行时候抛出无法找到入口函数foo的错误。
请问应该如何修改?其中a.dll放在/Winnt/System32目录下。
...全文
46 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
Muf 2003-04-12
  • 打赏
  • 举报
回复
至于DEF文件,在Visual studio.net中,可以由编译器生成,所以楼主没有遇到写DEF文件的问题。
不过Visual studio.net的BUG挺多的,建议有可能,还是尽量写写DEF文件,比较保险。
Knight94 2003-04-11
  • 打赏
  • 举报
回复
我写了一个类似的DLL
C的文件如下:CDllSample.cpp
#include "stdafx.h"
#include <stdio.h>
int _declspec(dllexport) foo();

int _declspec(dllexport) foo();
{
int a=10;
return a;
}

Dll的定义说明:CDllSample.def
EXPORTS
foo

调用声明如上。
Knight94 2003-04-11
  • 打赏
  • 举报
回复
把声明
[DllImport("a.dll",CharSet=CharSet.Unicode,EntryPoint="foo")]
extern static void foo();
应该为
[DllImport("a.dll", EntryPoint="foo", SetLastError=true,
CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall)]
extern static int foo();
试试,注意大小写。
ixMind 2003-04-11
  • 打赏
  • 举报
回复
用depends或dumpbin看一下a.dll里有没有foo这个导出函数
hahahawk 2003-04-11
  • 打赏
  • 举报
回复
把a.dll放在bin目录下,执行时候报错无法找到a.dll。放在winnt\system32下则能找到。
C#中调用的代码如下:
private void button1_Click(object sender, System.EventArgs e)
{
int a = 0;
try
{
a=foo();
}
catch(Exception mye)
{
MessageBox.Show(mye.Message);
return;
}
MessageBox.Show("Result=" + a);
}

[DllImport("mycdll.dll",CharSet=CharSet.Unicode,EntryPoint="foo")]
extern static void foo();

Knight94 2003-04-11
  • 打赏
  • 举报
回复
要么注册一下你的a.dll
Knight94 2003-04-11
  • 打赏
  • 举报
回复
你把你的a.dll放在C#程序目录bin下试试。

如果还不行的话,把你C#的调用dll声明的代码列出来,知道详情可能更好排错。
hahahawk 2003-04-11
  • 打赏
  • 举报
回复
谢谢Knight94。我在MSDN中找到一下信息:
模块定义 (.def) 文件为链接器提供有关被链接程序的导出、属性及其他方面的信息。生成 DLL 时,.def 文件最有用。由于存在可代替模块定义语句使用的链接器选项,通常不需要 .def 文件。也可以将__declspec(dllexport) 用作指定导出函数的手段。

在链接器阶段可以使用 /DEF(指定模块定义文件)链接器选项调用 .def 文件。

如果生成的 .exe 文件没有导出,使用 .def 文件将使输出文件较大并降低加载速度。

========================
/DLL
/DLL 选项生成作为主输出文件的 DLL。DLL 通常包含可由另一个程序使用的导出。有三种指定导出的方法,按照建议的使用顺序依次为:

源代码中的__declspec(dllexport)
.def 文件中的 EXPORTS 语句
LINK 命令中的 /EXPORT 规范
程序可使用一种以上的方法。

另一种生成 DLL 的方法是使用 LIBRARY 模块定义语句。将 /BASE 和 /DLL 选项连用等效于 LIBRARY 语句。

不要在开发环境中指定该选项;该选项只在命令行上可用。在用“应用程序向导”创建 DLL 项目时设置该选项。

在 Visual Studio 开发环境中设置此链接器选项

打开此项目的“属性页”对话框。有关详细信息,请参阅设置 Visual C++ 项目属性。
单击“配置属性”文件夹。
单击“常规”属性页。
修改“配置类型”属性。
以编程方式设置此链接器选项

Knight94 2003-04-11
  • 打赏
  • 举报
回复
而__declspec(dllexport)是属于在dll源码中的关键字,定义函数入口;而.def中是输出你的函数入口。
Knight94 2003-04-11
  • 打赏
  • 举报
回复
你用dll模板创建时,并没有.def文件,因为把定义供其它语言的程序使用,这一点,你可在老的msdn中查到,原话为:
EXPORTS definitions
This statement makes one or more definitions available as exports to other programs

有了它,别人再调用的时候,才能通过类似于entrypoint来找到函数入口。
hahahawk 2003-04-11
  • 打赏
  • 举报
回复
谢谢诸位,终于成功了。
当c中用extern __declspec(dllexport) int foo()
depends看到?foo@@YAHXZ
C#:
[DllImport("mycdll.dll", EntryPoint="?foo@@YAHXZ",CallingConvention=CallingConvention.Cdecl)]
此时用CallingConvention.StdCall也行。

当c中用extern "C" __declspec(dllexport) int foo();
depends看到的是foo
C#:
[DllImport("mycdll.dll", EntryPoint="foo",CallingConvention=CallingConvention.Cdecl)]
也行。

麻烦Muf,Knight94等兄能否详细说说"C",__declspec,WINAPI等的区别?
Knight94说的def文件请问如何在VC中创建?我用dll模板时候好像没有看到。
The_Gathering提到的depends工具真不错。我在学习《win2000技术内幕》的时候
还用过,可是就是没想到应用到这个时候。真笨。呵呵。
再次感谢大家。早知道有3位来回答这个问题,当时就该把分设高些,呵呵。
现在只有20分给啦。
Knight94 2003-04-11
  • 打赏
  • 举报
回复
给我个地址,我给你发过去。
Knight94 2003-04-11
  • 打赏
  • 举报
回复
如果你写Dll,没写def文件,那么调用此dll是不会成功的。
Muf 2003-04-11
  • 打赏
  • 举报
回复
有几个问题需要确认一下。
1. 函数的调用方式。
导出的foo函数是什么调用方式?__cdecl? WINAPI/StdCall?
如果不是WINAPI/StdCall,则需要CallingConvention=CallingConvention....来指定。
2. 函数名称
对于C++来说,函数的名称可能被转换过了。
如果使用extern "C"来说明函数,则函数名称仍按C标准。即foo
如果没有,则需要用完整转换后的名称:foo@@YAHXZ ,遇到这种情况,还是用函数ID号来指定的比较方便 。
建议使用extern"C"来说明导出函数。
The_Gathering 2003-04-11
  • 打赏
  • 举报
回复
正确的情况下应类似

1(0x0001) 0(0x0000) foo 0x000113ca
The_Gathering 2003-04-11
  • 打赏
  • 举报
回复
那就是,你的函数名被编译器编译的不叫foo了

把函数用extern "C"{}

或者写一个def文件就可以了

这样编译出来的入口函数才是foo这个名字
hahahawk 2003-04-11
  • 打赏
  • 举报
回复
Knight94:
我完全按照你的例子复制作了一次。还是报错找不到入口函数foo。
我建立了一个你说的.def文件,加入到vc的工程中,但是不知道它是否参加了编译。
我是用vc的环境编译C++的。
hahahawk 2003-04-11
  • 打赏
  • 举报
回复
用depends工具看到有如下一行:
1(0x0001) 0(0x0000) ?foo@@YAHXZ 0x000113ca
这应该说名有这个入口函数啊。
Knight94 2003-04-11
  • 打赏
  • 举报
回复
放在C++中,是dll的一个输出说明
The_Gathering 2003-04-11
  • 打赏
  • 举报
回复
我想是dll有问题,用Depends看看你的dll是不是正确的引出了函数
加载更多回复(1)

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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