C#與C++類型互轉(zhuǎn)

版權(quán)聲明:本文為Jumbo原創(chuàng)文章,采用[知識(shí)共享 署名-非商業(yè)性使用-禁止演繹 4.0 國(guó)際 許可協(xié)議],轉(zhuǎn)載前請(qǐng)保證理解此協(xié)議
原文出處:http://www.itdecent.cn/p/d3ac316104f8

一、C#調(diào)用DLL文件時(shí)參數(shù)對(duì)應(yīng)表

Wtypes.h 中的非托管類型    非托管 C 語(yǔ)言類型  托管類名    說明
HANDLE  void*   System.IntPtr   32 位
BYTE    unsigned char   System.Byte 8 位
SHORT   short   System.Int16    16 位
WORD    unsigned short  System.UInt16   16 位
INT int System.Int32    32 位
UINT    unsigned int    System.UInt32   32 位
LONG    long    System.Int32    32 位
BOOL    long    System.Int32    32 位
DWORD   unsigned long   System.UInt32   32 位
ULONG   unsigned long   System.UInt32   32 位
CHAR    char    System.Char 用 ANSI 修飾。
LPSTR   char*   System.String 或 System.StringBuilder    用 ANSI 修飾。
LPCSTR  Const char* System.String 或 System.StringBuilder    用 ANSI 修飾。
LPWSTR  wchar_t*    System.String 或 System.StringBuilder    用 Unicode 修飾。
LPCWSTR Const wchar_t*  System.String 或 System.StringBuilder    用 Unicode 修飾。
FLOAT   Float   System.Single   32 位
DOUBLE  Double  System.Double   64 位

二、C#調(diào)用C++編寫的DLL函數(shù), 以及各種類型的參數(shù)傳遞

  1. 如果函數(shù)只有傳入?yún)?shù),比如:
1.  //C++中的輸出函數(shù) 
2.  int __declspec(dllexport) test(const int N) 
3.  { 
4.  return N+10; 
5.  } 
對(duì)應(yīng)的C#代碼為:
C# Code Copy Code To Clipboard
1.  [DllImport("test.dll", EntryPoint = "#1")] 
2.  public static extern int test(int m); 
3.   
4.  private void button1_Click(object sender, EventArgs e) 
5.  { 
6.  textBox1.Text= test(10).ToString(); 
7.  } 
2. 如果函數(shù)有傳出參數(shù),比如:

1.  //C++
2.  void __declspec(dllexport) test(const int N, int& Z) 
3.  { 
4.  Z=N+10; 
5.  } 
對(duì)應(yīng)的C#代碼:
C# Code Copy Code To Clipboard
1.  [DllImport("test.dll", EntryPoint = "#1")] 
2.  public static extern double test(int m, ref int n); 
3.   
4.  private void button1_Click(object sender, EventArgs e) 
5.  { 
6.  int N = 0; 
7.  test1(10, ref N); 
8.  textBox1.Text= N.ToString(); 
9.  } 
3. 帶傳入數(shù)組:

1.  void __declspec(dllexport) test(const int N, const int n[], int& Z) 
2.  { 
3.  for (int i=0; i<N; i++) 
4.  { 
5.  Z+=n[i]; 
6.  } 
7.  } 
C#代碼:

1.  [DllImport("test.dll", EntryPoint = "#1")] 
2.  public static extern double test(int N, int[] n, ref int Z); 
3.   
4.  private void button1_Click(object sender, EventArgs e) 
5.  { 
6.  int N = 0; 
7.  int[] n; 
8.  n = new int[10]; 
9.  for (int i = 0; i < 10; i++) 
10. { 
11. n[i] = i; 
12. } 
13. test(n.Length, n, ref N); 
14. textBox1.Text= N.ToString(); 
15. } 
4. 帶傳出數(shù)組:
C++不能直接傳出數(shù)組,只傳出數(shù)組指針,

1.  void __declspec(dllexport) test(const int M, const int n[], int *N) 
2.  { 
3.  for (int i=0; i<M; i++) 
4.  { 
5.  N[i]=n[i]+10; 
6.  } 
7.  } 
對(duì)應(yīng)的C#代碼:

1.  [DllImport("test.dll", EntryPoint = "#1")] 
2.  public static extern void test(int N, int[] n, [MarshalAs(UnmanagedType.LPArray,SizeParamIndex=1)] int[] Z); 
3.   
4.  private void button1_Click(object sender, EventArgs e) 
5.  { 
6.  int N = 1000; 
7.  int[] n, Z; 
8.  n = new int[N];Z = new int[N]; 
9.  for (int i = 0; i < N; i++) 
10. { 
11. n[i] = i; 
12. } 
13. test(n.Length, n, Z); 
14. for (int i=0; i<Z.Length; i++) 
15. { 
16. textBox1.AppendText(Z[i].ToString()+"n"); 
17. } 
18. } 

這里聲明函數(shù)入口時(shí),注意這句 [MarshalAs(UnmanagedType.LPArray,SizeParamIndex=1)] int[] Z
在C#中數(shù)組是直接使用的,而在C++中返回的是數(shù)組的指針,這句用來轉(zhuǎn)化這兩種不同的類型.
關(guān)于MarshalAs的參數(shù)用法以及數(shù)組的Marshaling,可以參見這篇轉(zhuǎn)帖的文章: http://www.kycis.com/blog/read.php?21

  1. 傳出字符數(shù)組:
C++定義:
1.  void __declspec(dllexport) test(int i, double &a, double &b, char t[5])  
C#對(duì)應(yīng)聲明:

1.  [DllImport("dll.dll", EntryPoint = "test")]  
2.  public static extern void test(int i, ref double a, ref double b, [Out, MarshalAs(UnmanagedType.LPArray)] char[] t);   
4.              char[] t = new char[5];  
5.              test(i, ref a, ref b, t);  

字符數(shù)組的傳遞基本與4相似,只是mashalAs 時(shí)前面加上Out。

三、
1.普通傳值,如下面代碼中MotionDetect的第4個(gè)參數(shù);
2.傳引用,MotionDetect的第3個(gè)參數(shù),nNum傳進(jìn)動(dòng)態(tài)庫(kù)后賦值再傳回來;
3.引用傳一個(gè)結(jié)構(gòu)體,MotionDetect的第2個(gè)參數(shù),這里其實(shí)是傳一個(gè)結(jié)構(gòu)體的數(shù)組,具體像加ref的傳參還真不會(huì);
4.傳一個(gè)有分配內(nèi)存的變量,需要用到GCHandle,因?yàn)镃#是可以自動(dòng)回收內(nèi)存的,而GCHandle在這里的作用就是把它的內(nèi)存空間Pin住,傳遞給C++動(dòng)態(tài)庫(kù)后再手動(dòng)回收資源。

using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;

public class D : MonoBehaviour 
{
    struct Color_32
    {
        public byte r;
        public byte g;
        public byte b;
        public byte a;
    }
    Color_32[]  imageDataResult;
    
    GCHandle pixelsHandle;
    
    [DllImport("MotionDetectionDll")]
    private static extern bool MotionDetect( System.IntPtr colors, Color_32[] imageDataResult, ref int nNum, int nChannels );
    
    void Start()
    {
        imageDataResult = new Color_32[128*128];
    }
    
    void Update () 
    {
        int nNum = 0;
        pixelsHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
        bool wfDf = MotionDetect( pixelsHandle.AddrOfPinnedObject(), imageDataResult, ref nNum, 4 );
        pixelsHandle.Free();
    }
}
C++中是這么寫的
//頭文件中多加個(gè)結(jié)構(gòu)體定義
#include "stdafx.h"
struct Color_32
{
    byte r;
    byte g;
    byte b;
    byte a;
};
extern "C" _declspec(dllexport) bool MotionDetect ( char* imageData, Color_32 imageDataResult[], int *nNum, int nChannels );

// CPP文件中
extern "C" _declspec(dllexport) bool MotionDetect ( char* imageData, Color_32 imageDataResult[], int *nNum, int nChannels )
{
    IplImage* imgSrc = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 4);
    if(!imgSrc)
    {
        return false;
    }
    cvSetData( imgSrc, imageData, imgSrc->widthStep );
    
    ......
    
    for ( int i=0; i< ......; i++ )
    {
        imageDataResult[i].r = ......;
        imageDataResult[i].g = ......;
        imageDataResult[i].b = ......;
        imageDataResult[i].a = ......;
    }
    
    ......
    
    *nNum = 5;
    nChannels = 4;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,690評(píng)論 0 4
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡(jiǎn)單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 8,140評(píng)論 0 27
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,822評(píng)論 18 399
  • 歷史一直在重復(fù)某件事情,每一個(gè)人身上會(huì)發(fā)生相似的事情,因此我們需要重復(fù)的磨練,增加自己的閱歷。適應(yīng)歷史的潮流,順應(yīng)...
    扶光啟玄閱讀 403評(píng)論 0 0
  • 偶然的機(jī)會(huì)得到雪梅老師的引薦,于是參加了《家庭公約》“一次管一生的教育”的讀書計(jì)劃,春節(jié)后2月7日參加了第二次的讀...
    亞子_5226閱讀 3,394評(píng)論 1 1

友情鏈接更多精彩內(nèi)容