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

c++

在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)的

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

时间: 2024-09-23 15:19:50

在C#中使用C/C++写的DLL的相关文章

c#调用c++写的dll报错,尝试写入受保护的内存。。。求解答

问题描述 c#调用c++写的dll报错,尝试写入受保护的内存...求解答 private void button1_Click(object sender, EventArgs e) { IntPtr key = Marshal.AllocHGlobal(1024); //Marshal.ReleaseComObject(GenerateKeyEx); uint len = 4; string seed = "abcd"; uint slen = (uint)seed.Length;

怎样在C#中调用Delphi6写的DLL

我在编写一个系统时遇到了一个问题,无法在C#中调用Delphi6写的DLL,只因为DLL的参数是string类型的.然后在网上找相关的资料,还是没有结果.经过我的再三琢磨,现在已经解决,特写此文章与大家分享我的喜愉!Dellphi DLL文件:///////////////////////////////////////////////////////////////////library mydll; uses SysUtils, Classes; {$R *.res}function Out

c++-Qt中,怎么链接写好的C++功能实现

问题描述 Qt中,怎么链接写好的C++功能实现 在Qt中,怎么链接写好的C++功能实现 在Qt中,怎么链接写好的C++功能实现 在Qt中,怎么链接写好的C++功能实现 解决方案 Qt Manual中有对Library加载的详细说明,静态库只要加头文件所在目录,在代码中包含需要的头文件,并设置静态库lib所在目录到库目录中: 如果是dll,则需要dll import/export来标识需要导入/导出的类,然后设置lib相关目录,则可以在代码中使用dll中的类和函数了. 解决方案二: 链接无非就是链

js控制每个li滑到顶部时翻转90度离开,下滑时翻转90度进来中js代码怎么写啊

问题描述 js控制每个li滑到顶部时翻转90度离开,下滑时翻转90度进来中js代码怎么写啊 比如下面截图,当li滑到红色的区域时就翻转90度消失

在使用spring的过程中,service层写在配置文件中好呢还是注解配置好呢?

问题描述 在使用spring的过程中,service层写在配置文件中好呢还是注解配置好呢? 在使用spring的过程中,service层写在配置文件中好呢还是注解配置好呢?在配置文件中是这样的注解配置时这样的@Service(""userService"")说说理由哦. 解决方案 一般应用性开发使用注解就可以.它较xml配置方式的优势在于省去了xml复杂的配置,而且不需要维护两套内容(xml配置方式需要维护service类和xml文件).但是如果需要修改相关内容,注

文件操作-多线程中对文件进行写操作

问题描述 多线程中对文件进行写操作 我的多线程部分程序是这样的: UINT ClientThread(LPVOID pParam) { EnterCriticalSection(&cs); Cw_dispctrlDlg dlg=(Cw_dispctrlDlg)pParam; while(true) { -- -- dlg->file_net.Open(dlg->str_file_netpath, CFile::modeCreate | CFile::modeNoTruncate | C

二维数组-C#中如何大幅提高写excel文件的速度?

问题描述 C#中如何大幅提高写excel文件的速度? 输入文件:input.txt包含以[:]号或者[t]制表符分隔的多行(实际在100万行以上)数据,每行数据个数不定. a;b;c 1;2; 1;2;3;4;5 输出文件;output.xlsx a b c 1 2 1 2 3 4 5 问题:写了个小程序处理2000行在10s以内,百万行速度就太慢,无法忍受了.求教一些能显著提高写Excel速度的方法.网上查的先变成二维数组之类的方法,效果不大.百万行在20min以内就好. 解决方案 你完全没有

代码-java中怎么引用自己写的函数

问题描述 java中怎么引用自己写的函数 我是一个java新手,写了一段代码,有关:摄氏度和华氏度之间的互相转化 package method; import method.HuaShe; public class TestCToFandFToC { public static void main(String[] args){ System.out.println("摄氏 华氏 华氏 摄氏"); for(int i = 1;i <= 10;i++){ double she1 =

python-求助各位~一个有关linux中.sh脚本里写循环的问题,谢谢O(∩_∩)O~

问题描述 求助各位~一个有关linux中.sh脚本里写循环的问题,谢谢O(∩_∩)O~ a = [""name1""name2""name3""......""name100""] for i in 路径/*.py #这个路径底下有100个python脚本名字不同,代码一样do 我需要把每个python文件打开,改动一行if name = """"