C 呼叫dll 封送結構體 結構體陣列

2021-06-20 20:38:15 字數 3418 閱讀 3954

一. 

結構體的傳遞

cpp **

#define jnaapi extern "c" __declspec(dllexport) // c方式匯出函式

typedef struct

osinfo;

// 1. 獲取版本資訊(傳遞結構體指標)

jnaapi bool getversionptr( osinfo *info );

// 2.獲取版本資訊(傳遞結構體引用)

jnaapi bool getversionref(osinfo &info);

可以通過二種方式來呼叫:

c#**

// osinfo定義

[structlayout(layoutkind.sequential)]

public struct osinfo

1. 方式一(傳入

結構體引用

),在c#中,結構體是以傳值方式傳遞,類才是以傳位址方式傳遞,加關鍵字ref即可. c端傳遞了兩種不同型別的引數,都可以通過引用來解決.

c#**

[dllimport("jnalib.dll", entrypoint = "getversionptr")]

public static extern bool getversionptr(ref osinfo info);

public static extern bool getversionref(ref osinfo info);

2. 方式二(

傳入intptr

(平台通用指標))

cpp**

intptr pv = marshal.allochglobal(148); //結構體在使用時一定要分配空間(4*sizeof(int)+128)

marshal.writeint32(pv,148); //向記憶體塊裡寫入數值

if (getversionptr(pv)) //直接以非託管記憶體塊位址為引數

", marshal.readint32(pv, 0));

console.writeline("--major:",marshal.readint32(pv, 4)); //移動4個位元組

console.writeline("--buildnum: " + marshal.readint32(pv, 12));

console.writeline("--szversion: "+marshal.ptrtostringansi((intptr)(pv.toint32()+20)));

}marshal.freehglobal(pv); //處理完記得釋放記憶體

二.

結構體陣列的傳遞

cpp**

// 傳遞結構體指標

jnaapi bool getversionarray(osinfo *info,int nlen);

呼叫**:

c#**

/**

* c#介面,對於包含陣列型別,只能傳遞intptr

*/ [dllimport("jnalib.dll", entrypoint = "getversionarray")]

public static extern bool getversionarray(intptr p, int nlen);

// 源目標引數

osinfo infos = new osinfo[2];

for (int i = 0; i < infos.length; i++)

intptr ptarr = new intptr[1];

ptarr[0] = marshal.allochglobal(marshal.sizeof(typeof(osinfo)) * 2); //分配包含兩個元素的陣列

intptr pt = marshal.allochglobal(marshal.sizeof(typeof(osinfo)));

marshal.copy(ptarr, 0, pt, 1); //拷貝指標陣列

getversionarray(pt, 2); //呼叫

//還原成結構體陣列

for (int i = 0; i < 2; i++)

szversion:", infos[i].osversion, infos[i].szversion);

}

三. 

複雜結構體的傳遞

1. 輸出引數,結構體作為指標傳出

cpp**

typedef struct

student;

// class中包含結構體陣列型別

typedef struct

class;

// 傳入複雜結構體測試

jnaapi int getclass(class *pclass,int len);

c#**

// 介面定義 

[dllimport("jnalib.dll", entrypoint = "getclass")]

public static extern int getclass(intptr pv,int len);

// 結構體定義

// student

[structlayout(layoutkind.sequential)]

public struct student

// class

[structlayout(layoutkind.sequential)]

public struct class

// 呼叫複雜結構體測試

int size = marshal.sizeof(typeof(class)) * 50;

intptr pbuff = marshal.allochglobal(size); // 直接分配50個元素的空間,比marshal.copy方便多了

getclass(pbuff, 50);

class pclass = new class[50];

for (int i = 0; i < 50; i++)

marshal.freehglobal(pbuff); // 釋放記憶體

2. 輸入引數, 給複雜結構體賦值後作為輸入引數傳入

對於比較大的結構體指標,無法直接應用結構體型別,轉化成intptr型別, 此時需要將原生型別轉化為指標,並給指標賦值

呼叫方法: marshal.structuretoptr(stu, ptr1, true) 

C 呼叫C C 動態庫 封送結構體,結構體陣列

一.結構體的傳遞 cpp define jnaapi extern c declspec dllexport c方式匯出函式 typedef struct osinfo 1.獲取版本資訊 傳遞結構體指標 jnaapi bool getversionptr osinfo info 2.獲取版本資訊 傳...

平台呼叫 結構的封送

關於結構的封送,先看乙個類 structlayoutattribute 該類的作用是,允許控制記憶體中類或結構的資料字段的物理布局。該類的層次結構為 system.object system.attributesystem.runtime.interopservices.structlayoutat...

結構體巢狀結構體 C語言結構體

希望今年夏天的遺憾能成為你秋天的驚喜。網易雲熱評 一 結構體概念 可以簡單理解為把不同資料型別放到一起的陣列 二 結構體宣告與初始化 1 先宣告結構體型別再定義變數 2 同時定義變數 3 直接定義結構體型別變數 include include include include struct aiyou...