在C#中使用C/C++写的DLL

原创 2002年12月30日 09:23:00

在C#中使用C/C++写的DLL

呵呵..,又到了我有想写点东西的时候了.最近在论坛老是看见有朋友问

C/C++的程序如何在C#中使用?其实这是个很不错的想法.代码复用.不过

托管程序如何使用非托管代码呢?想想看,很自然就联想到了DLL动态连接库

把C/C++的代码编译成DLL,然后使用,这里我假设我的C/C++代码里包含一个

函数,叫average(int av[])

申明如下:
extern "C" __declspec(dllexport) __cdecl int average(int *av);

实现嘛就更简单了
__declspec(dllexport) __cdecl int average(int av[])
{
int i=0;
int sum=0;
  while(av)
{
  sum+=av[i];
   i++;
}
return sum/i;
}//随手写的也许有点问题

好了不管那么多,让我们来看看C#的代码是如何实现的,我想你应该想的到

是什么?猜猜看,OK,我想你至少能想到两个英文单词dll import,是的你猜对了

DLLImport 属性,就是它,看看它有些什么,我可以用到,MSDN是最好的选择.看见了吗

是的,准确地说,DllImport 属性具有下列行为:

它只能放置在方法声明上。

它具有单个定位参数:指定包含被导入方法的 dll 名称的 dllName 参数。

它具有五个命名参数:
 

CallingConvention 参数指示入口点的调用约定。如果未指定 CallingConvention,则使用默认值
CallingConvention.Winapi。

CharSet 参数指示用在入口点中的字符集。如果未指定 CharSet,则使用默认值 CharSet.Auto。

EntryPoint 参数给出 dll 中入口点的名称。如果未指定 EntryPoint,则使用方法本身的名称。

ExactSpelling 参数指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配。如果未指定
ExactSpelling,则使用默认值 false。

PreserveSig 参数指示方法的签名应当被保留还是被转换。当签名被转换时,它被转换为一个具有
HRESULT 返回值和该返回值的一个名为 retval 的附加输出参数的签名。如果未指定 PreserveSig,则使
用默认值 true。

SetLastError 参数指示方法是否保留 Win32“上一错误”。如果未指定 SetLastError,则使用默认值

false。

它是一次性属性类。

此外,用 DllImport 属性修饰的方法必须具有 extern 修饰符。

是的,上面就是MSDN原文内容.好了继续我们的例子,好了,先把我们上面的C代码编译成DLL

叫什么呢?那就叫MYDLLTest好了.

[DllImport("MYDLLTest.dll",EntryPoint="average",ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)]
static extern int average(int av[]);

好了,该是你找个地方写一句的时候了

如:

int[5] i={1,2,3,4,5};
int j=average(i);

 


好了,你看到了,就是这样的,可是事实上并没有你想的那么简单.因为设计到很多问题

你看上面的例子中,int是在C#和C/C++中都有的,可是如果是char *呢?也许你会说string

可是你看在C/C++中这些都表示字符串(char*,or wchar_t*,or BSTR, ..)那我们该怎么办?

想想看,还有些什么?属性吗?是的,找找,对了我似乎想到一个单词.Marshal恩..记得它吗?

别告诉我,你会把它拼成马歇尔.哈哈..开个玩笑是列集.我们在MSDN上输入看看找到什么了?

是的MarshalAs.看看MSDN上说些什么?"指示应如何在托管代码和非托管代码之间封送数据"

哈哈.看来不错呢.在看看下面的备注:

可将该属性应用于参数、字段或返回值。

该属性为可选属性,因为每个数据类型都有默认的封送处理行为。仅在可以将给定类型封送到多个类型时需要此属性。例如,String 可能作为 LPStr、LPWStr、LPTStr 或 BStr 封送到非托管代码。默认情况下,字符串作为 BStr 封送到 COM 方法。可将 MarshalAsAttribute 属性应用于个别的字段或参数,以使该字符串作为 LPStr 而非 BStr 封送。有关如何使用此属性的完整详细信息,请参阅“数据封送处理规范”。

大多数情况下,该属性只是使用 UnmanagedType 枚举标识非托管数据的格式,如下面的示例所示。

[C#]
void MyMethod([MarshalAs(LPStr)] String s);
某些 UnmanagedType 枚举需要附加信息。例如,当 UnmanagedType 为 LPArray 时需要附加信息。有关如何使用此属性的完整说明,请参阅“数据封送处理规范”。

瞧见了,正是我们需要的对吗?好了,我就写怎么多了,事实上,还有关于结构(struct)的

这就需要,你来完成了.希望对你有点帮助.(完)

C++写dll文件用C#调用

创建项目: 项目为win32项目,注意不是控制台,然后在设置处选上DLL并勾上“导出项目”,见下图 开始写c++: 把和项目同名的.h文件和.cpp文件清空,添加如下代码://在头文件中...
  • qq_22033759
  • qq_22033759
  • 2015年08月29日 23:52
  • 2106

在VS2015中用C++创建DLL并用C#调用且同时实现对DLL的调试

在VS2015中用C++创建DLL并用C++或C#调用且同时实现对DLL的调试
  • songyi160
  • songyi160
  • 2016年04月06日 17:59
  • 13376

C#与C++的混合编程 之二 使用非托管dll 导出标准函数

C#与C++的混合编程 之二  使用非托管dll 导出标准函数
  • fang1192801693
  • fang1192801693
  • 2015年11月29日 12:40
  • 853

C#调用DLL的几种方法,包括C#调用C\C++\C#DLL

C#中dll调用方法 一、      DLL与应用程序 动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要...
  • AAA123524457
  • AAA123524457
  • 2016年11月20日 17:46
  • 9446

平台调用之如何利用VS2013 C#调试C++DLL库

对于托管代码调用非托管DLL文件,已经是非常普遍的事情,下面写一下如何通过托管代码(C#)像调试托管代码一样调试DLL中的代码。 注意:【dll工程和调用dll的exe工程需要在同一个解决方案中】 ...
  • gggg_ggg
  • gggg_ggg
  • 2016年04月07日 15:13
  • 2926

Eclipse for C/C++ (三)编写DLL文件之def文件的使用

一、def文件说明 通常我们编写动态链接库时,一般使用的都是vc或vs等相关的集成开发环境。在编写的过程中,当使用__stdcall 标准方式调用时,有一个问题是经常遇到的,那就是导出的函数名的问题...
  • nodototao
  • nodototao
  • 2016年09月20日 22:15
  • 1407

C#项目中调用C++生成的Dll 入门教程

如何在C#中调用C++生成的DLL文件
  • guoyk1990
  • guoyk1990
  • 2016年06月30日 21:36
  • 2539

C#调用C/C++动态链接库(.dll)详解

第一篇编译C的动态连接库 在实际工作中,我们经常会将C语言中的.lib和.h文件(静态库)编译成动态连接库.dll文件(这里只提供这两种文件,没有完整的工程),以提供给其他语言平台调用。 ...
  • tery001
  • tery001
  • 2014年06月04日 15:21
  • 1654

C#中调用C++的dll的参数为指针类型的导出函数(包括二级指针的情况)

一:首先什么是IntPtr 先来看看MSDN上说的:用于表示指针或句柄的平台特定类型。这个其实说出了这样两个事实,IntPtr 可以用来表示指针或句柄、它是一个平台特定类型。对于它的解释,这个哥...
  • u010159842
  • u010159842
  • 2016年06月27日 10:49
  • 2613

C#调用带结构体指针的C Dll的方法

在C#中调用C(C++)类的DLL的时候
  • cumtwys
  • cumtwys
  • 2014年07月31日 11:39
  • 6244
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在C#中使用C/C++写的DLL
举报原因:
原因补充:

(最多只允许输入30个字)