C#调用C++动态库DLL结构指针函数问题?

C#调用C++动态库DLL结构指针函数问题?,第1张

LZ试下这个:

源代码用VBNET写得,机器转化成C#的,加了很多命名空间的引用。VBNET里只需要引用systemruntimeinteropservices就可以了。

using MicrosoftVisualBasic;

using System;

using SystemCollections;

using SystemCollectionsGeneric;

using SystemData;

using SystemDiagnostics;

using systemruntimeinteropservices;

public class APIWrap

{

public struct SMSMessageStruct

{

[MarshalAs(UnmanagedTypeByValTStr, sizeconst = 256)]

public string Msg;

[MarshalAs(UnmanagedTypeByValTStr, sizecounst = 32)]

public string PhoneNo;

[MarshalAs(UnmanagedTypeByValTStr, sizecounst = 32)]

public string ReceTime;

}

[Dllimport("SMSDLLdll", EntryPoint = "SMSGetNextMessage")]

public static extern int SMSGetNextMessage( [In(), Out()]

ref SMSMessageStruct Msg);

}

函数的返回值可以是指向结构体的指针 例子: //首先定义结构体 struct lwip_socket { struct netconn conn; struct netbuf lastdata; u16_t lastoffset; u16_t rcvevent; u16_t sendevent; u16_t flags; int err; }; //定义一个此结构体变量,

请参考:

C++:

struct STL

{

int nSn;

short nLic;

};

extern "C" LICC_API int __cdecl LicenseCheck2(const STL stl);

C#:

    [StructLayout(LayoutKindSequential)]

    public struct STL

    {

        public int nSn;

        public short nLic;

    };                

    STL stl= new STL();

    stlnLic = 1;

    stlnSn = 3;

    IntPtr ptr =  MarshalAllocHGlobal(MarshalSizeOf(stl));

    MarshalStructureToPtr(stl, ptr, true);

    int length = LicenseCheck2(ptr);

    MarshalFreeHGlobal(ptr);

如果结构体中所有数据都是函数调用时需指定的参数,那么就不算破坏dll封装性。

如果结构体只有部分数据是函数调用时需要指定的,那么可以将结构体中的成员作为函数参数传递过去,比如:

struct S{

A;

B;

C;

};

只需要成员A和B,所以函数可是这样:void Function(A,B);

或者另外定义一个结构体作为接口:

struct Y

{

A,

B

};

函数数可以是这样:void Funtion(Y p_y);

C#无法直接调用这种参数的函数,C#中你描述的那种二维数组,本质上跟一维数组一致。倒是single[][]跟float是类似的,但是也不能直接传递。

然后具体说说

float arr arr为指向float型的指针

single[] arr arr为single型数组的引用,当传递给API时,会自动传递内部指针,这个指针才真真的指向single型的指针

float arr arr为一个指向float型指针的指针,即arr[]应该是一个float型指针

single[][] arr arr为一个single型数组引用的数组引用,这意味着arr的内部指针指向的是single[]型引用的指针,跟指向single型指针完全是两码事

综上所述,C#不能直接调用Test(float arr,int rows,int cols),你必须使用非安全代码构造一个single[],然后将这个数组传递过去。下面是一个例子

[DllImport("testdll")]

static extern unsafe bool Test(float[] arr, int row, int col);//这里arr要声明为float[],使用起来比较方便

bool CallTest(float[,] arr)

{

int row = arrGetUpperBound(0) + 1;

int col = arrGetUpperBound(1) + 1;

unsafe

{

fixed(float fp=arr)

{

float[] farr=new float[row];

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

{

farr[i] = fp + i col;

}

return Test(farr, row, col);

//如果Test(float arr, int row, int col)这样声明,就要用下面的方法调用

//fixed(float fpp=farr)

//{

// return Test(fpp, row, col);

//}

}

}

}

VB里没有指针类型,所以返回的char应该定义成Long,返回的指针不会自动变成字符串的,没有那么先进。返回指针VB就真的会得到一个"指针"。

Public Type VARVALUE

value As Long Long对应C中的指针类型

valType As Byte Byte对应C的Char

valLength As Long 注意!C语言中写作int但是windows中int和long长度相同!VB的Integer在C语言中应该是short型!

End Type

想从返回的"指针"中获取数据可以用CopyMemory,得到一个VB变量的"指针"需要用VarPtr(这是内置函数不是API)

我还做不出来DLL所以没法试验,应该是这样没错(参考VB中使用API的方法就可以了,因为API基本上都是C语言编的DLL

type

TABC

=

packed

record

m_puser:

LPVOID;

cSaa:

BYTE;

end;

TPABC

=

@TABC;

function

myinid(hWnd:HWND;

cSaa:BYTE):TPABC;

这样就OK了

我假设你的DLL_API定义为

__declspec(dllexport)

function

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/12157820.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-21
下一篇2023-05-21

发表评论

登录后才能评论

评论列表(0条)

    保存