C#调用C++DLL

原文连接: http://blog.csdn.net/qiuhua1231232006/article/details/56277338


在合作开发时,C#时常需要调用C++DLL研究了一下C#,发现其强大简洁, 在跨语言调用方面封装的很彻底,提供了强大的API与之交互.这点比JNA方便多了. Java与C#都只能调用C格式导出动态库,因为C数据类型比较单一,容易映射. 两者都是在本地端提供一套与之映射的C#/java描述接口,通过底层处理这种映射关系达到调用的目的.

1、调用例子(例子中提供了传值调用和传址调用两种方法):

C++代码(C++生成动态库DLL.dll):

Lib.h


[cpp]  view plain  copy
  1. //文件:lib.h  
  2. #pragma once  
  3.   
  4. #include <string>   
  5. using namespace std;    
  6.   
  7. #define JNAAPI extern "C" __declspec(dllexport) // C方式导出函数  
  8.   
  9. typedef struct CARDINFO  
  10. {  
  11.     int majorVersion;  
  12.     int minorVersion;  
  13.     int cardType;  
  14.     char szDescribe[128];  
  15. };  
  16.   
  17. // 1. 获取版本信息(传递结构体指针)      
  18. JNAAPI bool GetVersionPtr(CARDINFO *info);  
  19. // 2.获取版本信息(传递结构体引用)      
  20. JNAAPI bool GetVersionRef(CARDINFO &info);  

Lib.cpp

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2. #include "lib.h"  
  3. #include <stdlib.h>  
  4.   
  5. using namespace std;  
  6.   
  7. // 1. 获取版本信息(传递结构体指针)      
  8. bool GetVersionPtr(CARDINFO *info)  
  9. {  
  10.     info->majorVersion = 1;  
  11.     info->minorVersion = 22;  
  12.     info->cardType = 3;  
  13.     memcpy(info->szDescribe, "hello world", 128);  
  14.   
  15.     return true;  
  16. }  
  17.   
  18. // 2.获取版本信息(传递结构体引用)      
  19. bool GetVersionRef(CARDINFO &info)  
  20. {  
  21.     info.majorVersion = 1;  
  22.     info.minorVersion = 22;  
  23.     info.cardType = 3;  
  24.     memcpy(info.szDescribe, "hello world", 128);  
  25.   
  26.     return true;  
  27. }  

C#代码(C++生成动态库DLL.dll):

[cpp]  view plain  copy
  1. class CCommand  
  2. {  
  3.     const string dllpathfile = "..\\..\\..\\..\\Lib\\DLL.dll";  
  4.   
  5.     // CARDINFO定义    
  6.     [StructLayout(LayoutKind.Sequential)]  
  7.     public struct CARDINFO  
  8.     {  
  9.         public int majorVersion;  
  10.         public int minorVersion;  
  11.         public int cardType;  
  12.         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]  
  13.         public string szDescribe;  
  14.     }  
  15.   
  16.     [DllImport(dllpathfile, EntryPoint = "GetVersionPtr")]  
  17.     public static extern bool GetVersionPtr(ref CARDINFO info);  
  18.   
  19.     [DllImport(dllpathfile, EntryPoint = "GetVersionRef")]  
  20.     public static extern bool GetVersionRef(ref CARDINFO info);  
  21. }     

调用:

[csharp]  view plain  copy
  1. //C#调用C++库  
  2. CCommand.CARDINFO cardInfo = new CCommand.CARDINFO();  
  3. CCommand.GetVersionPtr(ref cardInfo);  



2、类型转换说明:

类型对照:

C++类型

C#类型

BSTR

StringBuilder

LPCTSTR

StringBuilder

LPCWSTR

IntPtr

handle

IntPtr

hwnd

IntPtr

char *

string

int *

ref int

int &

ref int

void *

IntPtr

unsigned char *

ref byte

CLR Type

Win32 Types

System.SByte

char, INT8, SBYTE, CHAR

System.Int16

short, short int, INT16, SHORT

System.Int32

int, long, long int, INT32, LONG32, BOOL , INT

System.Int64

__int64, INT64, LONGLONG

System.Byte

unsigned char, UINT8, UCHAR , BYTE

System.UInt16

unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR , __wchar_t

System.UInt32

unsigned, unsigned int,

UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT

System.UInt64

unsigned __int64,

UINT64, DWORDLONG, ULONGLONG

System.Single

float, FLOAT

System.Double

double, long double, DOUBLE

注:

C#中类型转换接口:

string转为IntPtr

IntPtrSystem.Runtime.InteropServices.Marshal.StringToCoTaskMemAuto(string)

 

IntPtr转为string

stringSystem.Runtime.InteropServices.MarshalPtrToStringAuto(IntPtr)


3、代码分析

C#为了用上C++的代码,只好研究下从C# 中调用DLL,首先必须要有一个声明,使用的是DllImport关键字,包含DllImport所在的名字空间

[csharp]  view plain  copy
  1. using System.Runtime.InteropServices;  
  2. class CCommand  
  3. {  
  4.     conststringdllpathfile ="..\\..\\..\\..\\Lib\\DLL.dll";  
  5.     [DllImport(dllpathfile, EntryPoint ="GetVersionPtr")]  
  6.     publicstaticexternboolGetVersionPtr(refCARDINFOinfo);  
  7. }  

DllImport关键字作用是告诉编译器入口点在哪里,并将打包函数捆绑在这个类中,在类中,直接调用GetVersionPtr,在其他的类中调用CCommand.GetVersionPtr

[DllImport(dllpathfile)]在申明的时候还可以添加几个属性
[DllImport(dllpathfile, EntryPoint="GetVersionPtr ",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)
]
EntryPoint: 指定要调用的 DLL 入口点。默认入口点名称是托管方法的名称 。
CharSet: 控制名称重整和封送 String 参数的方式 (默认是UNICODE)
CallingConvention指示入口点的函数调用约定(默认WINAPI) 
SetLastError 指示被调用方在从属性化方法返回之前是否调用 SetLastError Win32 API 函数 (C#中默认false )


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值