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