
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
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)