c# Task.Factory.StartNew 传参数_C#/C++混合编程一二事
生活随笔
收集整理的這篇文章主要介紹了
c# Task.Factory.StartNew 传参数_C#/C++混合编程一二事
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
C#/C++混編的情形經常會碰到,下面就來講一講一些需要注意的點。廢話不多說,Let's get started. (時間有限,暫時沒有寫完,后續會持續更細。如果有寫的不嚴謹甚至錯誤的地方歡迎大家指正)
一、C++導出函數的聲明
在導出函數的頭文件,經常見到如下的模板
#pragma once下面就來給出解釋。
- #ifdef __cplusplus這條預編譯指令。如果項目是C++的項目,則用extern "C" {} 將所有的代碼包起來。這樣的好處是導出的函數名仍和代碼中定義的一致,否則函數名前后會加上一些看起來很奇怪的符號。這是因為C++的函數有重載機制,同一個函數名,可以有多種參數形式,不加extern "C"包起來的話,編譯器就會在函數名前后加上一些符號,來具體到這個函數的具體的某一種形式。
- #ifdef YOURPROJECT_EXPORTS這條預編譯指令。這段話的意思就是如果定義了YOURPROJECT_EXPORTS這個宏,則把YOURPROJECT_API這個宏定義成__declspec(dllexport),否則把YOURPROJECT_API定義成__declspec(dllimport)。這個設計是為了開發者和調用者的便利性設計的。因為這個頭文件,后來也會拷貝給調用者用,開發者的導出函數的這個項目中定義一個宏YOURPROJECT_EXPORTS,而調用者那邊沒有這個宏。所以YOURPROJECT_API對于開發者就是__declspec(dllexport),對于調用者就是__declspec(dllimport)。__declspec(dllexport)告訴編譯器這是一個需要導出的函數,__declspec(dllimport)告訴編譯器這是一個從外部的庫文件中導入的函數。
- #define CALLINGCONVENTION _cdecl 這個宏,就是調用約定,可以根據需要把它定義成__cdecl或者__stdcall或者其他。調用約定關系到函數參數入棧和出棧的清理方式。常見的有__cdecl、_stdcall、_fastcall. 最常用的就是_cdecl、_stdcall. 如果調用方用C#,則推薦用_cdecl. 因為_stdcall也會像沒加extern "C" 那樣導致導出的函數名和頭文件中定義的不一致。(__cdecl許多人記不住,其實它就是C Declaration的縮寫)
二、C++導出函數的實現
聲明寫好了,實現就簡單了。參考如下,不解釋。
#include三、C#導入函數的聲明
C#調用之前,先寫一個類,里面用來聲明從C++導入的函數
class說明:
- 記得添加命名空間using System.Runtime.InteropServices;
- 函數聲明前寫上DllImport屬性,包含導入的庫文件名,調用約定,字符集,入口點。
- 庫文件名可以寫相對路徑,也可以寫絕對路徑。
- 調用約定和C++保持一致,推薦用Cdecl方式,如果強行用Stdcall會直接報錯。
- 字符集可寫可不寫,一般不會用上。但是如果C++參數中有char*或者wchart*時,就需要根據實際情況填寫字符集這個屬性。如果參數為wchar_t*時,指定字符集為Unicode, C#的參數使用string即可(當然也可以使用StringBuilder,具體不討論)。當然也可以不指定字符集,在參數前加上如下聲明[MarshalAs(UnmanagedType.LPWStr)]也可。
- 入口點,就是dll中導出的函數的符號,當且僅當調用約定為__cdecl、并且加了extern "C"包裝的情況下,入口點才和函數名相同。
四、參數的傳遞
- 基本類型,比如int、float、double這些直接傳就好,不再贅述。
- 字符串類型。舉個例子:
- 一般指針,比如void*、自定義類的指針YourClass*、句柄如HANDLE、HWND等。舉個例子
- 函數指針。這種情形,C++需要一個函數指針,C#傳委托即可。舉個例子
- 結構體指針。
- 參照C++端定義的結構體也在C#端定義同樣的結構體,具體參見第六節。然后C#的形參用ref YourStruct類型,C++端用YourStruct*接收。
五、返回值的傳遞
基本類型基本可以直接聲明,這里就把特殊的返回值拿出來提一下
- bool類型:如果按照常規的寫法,返回值總是錯誤的。我搜索了stackoverflow,發現了這個問題的解決方案,參考鏈接如下:
因此,聲明就應該這樣寫:
YOURPROJECT_API [DllImport(strDllName, CallingConvention = ccDef, CharSet = csDef, EntryPoint ="DoSomething")]六、復雜的數據類型的定義(結構體)
總結
以上是生活随笔為你收集整理的c# Task.Factory.StartNew 传参数_C#/C++混合编程一二事的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: max日期最大值为0_excel函数技巧
- 下一篇: python安装后无法运行任何软件_为啥