如何在C語(yǔ)言中調(diào)用DLL并傳遞指針?
當(dāng)我們需要在C語(yǔ)言中調(diào)用其他語(yǔ)言編寫的動(dòng)態(tài)鏈接庫(kù)(DLL),就需要注意參數(shù)的傳遞方式。本文將介紹如何在C語(yǔ)言中正確地傳遞指針。使用操作Dll的類空間為了更好地操作DLL,我們可以使用一個(gè)封裝了各種AP
當(dāng)我們需要在C語(yǔ)言中調(diào)用其他語(yǔ)言編寫的動(dòng)態(tài)鏈接庫(kù)(DLL),就需要注意參數(shù)的傳遞方式。本文將介紹如何在C語(yǔ)言中正確地傳遞指針。
使用操作Dll的類空間
為了更好地操作DLL,我們可以使用一個(gè)封裝了各種API函數(shù)的類。這個(gè)類可以提供給我們方便易用的方法,避免繁瑣的代碼實(shí)現(xiàn)和不必要的麻煩。
VC原型代碼:
```c
class DllWrapper {
private:
HMODULE m_hModule;
public:
DllWrapper(LPCTSTR lpctszModuleName);
~DllWrapper();
FARPROC GetProcAddress(LPCSTR lpProcName);
// 方法列表
};
```
根據(jù)數(shù)據(jù)的長(zhǎng)度申請(qǐng)非托管空間異常拋出代碼
當(dāng)我們需要傳遞指針時(shí),需要注意內(nèi)存的分配問(wèn)題。如果我們使用C語(yǔ)言的malloc函數(shù)進(jìn)行內(nèi)存分配,而忘記釋放內(nèi)存,則會(huì)引起內(nèi)存泄漏等問(wèn)題。為此,我們可以使用Windows API函數(shù)GlobalAlloc和GlobalFree來(lái)申請(qǐng)和釋放非托管堆上的內(nèi)存。
```c
include
void* AllocateMemory(size_t cBytes) {
void* pvRet ::GlobalAlloc(GMEM_FIXED, cBytes);
if (pvRet NULL) {
throw std::bad_alloc();
}
return pvRet;
}
void FreeMemory(void* pv) {
::GlobalFree(pv);
}
```
要申請(qǐng)非托管空間的數(shù)據(jù)代碼
接下來(lái),我們需要在DLL中定義一些函數(shù),以便在C程序中調(diào)用。例如,我們可以在DLL中定義一個(gè)函數(shù)來(lái)分配內(nèi)存,并返回指向該內(nèi)存的指針。
```c
extern "C" __declspec(dllexport)
LPVOID AllocateMemory(SIZE_T cb) {
return ::LocalAlloc(LPTR, cb);
}
```
指向非托管空間的指針?lè)椒ùa
當(dāng)我們需要獲取指向非托管內(nèi)存的指針時(shí),可以使用Marshal類中的PtrToStructure函數(shù)。該函數(shù)將非托管內(nèi)存塊中的內(nèi)容復(fù)制到托管結(jié)構(gòu)體中,并返回一個(gè)指向該結(jié)構(gòu)體的指針。
```c
include
include
using namespace System::Runtime::InteropServices;
using namespace msclr::interop;
struct MyStruct {
int a;
double b;
};
MyStruct* pMyStruct new MyStruct;
pMyStruct->a 123;
pMyStruct->b 456.789;
// 將非托管內(nèi)存中的數(shù)據(jù)復(fù)制到托管結(jié)構(gòu)體中,并返回指向該結(jié)構(gòu)體的指針
IntPtr ptr Marshal::AllocHGlobal(sizeof(MyStruct));
Marshal::StructureToPtr(*pMyStruct, ptr, false);
MyStruct* pMyStruct2 static_cast
```
傳入指針數(shù)組(指針指向自定的結(jié)構(gòu)體)方法代碼
當(dāng)我們需要傳遞指針數(shù)組時(shí),我們可以先將數(shù)組中的每個(gè)元素轉(zhuǎn)換為指向非托管內(nèi)存的指針,然后將這些指針傳遞給DLL函數(shù)。
```c
include
include
std::vector
std::for_each((), vecMyStruct.end(), [](MyStruct obj) {
obj.a rand();
obj.b drand48();
});
std::vector
std::transform((), vecMyStruct.end(), (), [](const MyStruct obj) {
IntPtr ptr Marshal::AllocHGlobal(sizeof(MyStruct));
Marshal::StructureToPtr(obj, ptr, false);
return ();
});
MyStruct ppMyStructArray reinterpret_cast
int nSize static_cast
MyDLLFunction(ppMyStructArray, nSize);
for (auto ptr : vecPointers) {
Marshal::FreeHGlobal(IntPtr(ptr));
}
```
總結(jié):
在C語(yǔ)言中調(diào)用其他語(yǔ)言編寫的DLL時(shí),指針的傳遞是一個(gè)重要的問(wèn)題。通過(guò)使用操作DLL的類空間、申請(qǐng)非托管空間、指向非托管空間的指針?lè)椒ㄒ约皞魅胫羔様?shù)組,我們可以在C語(yǔ)言中有效地傳遞指針。