[英]Pointers in C# to Retrieve Reference From DllImport Function
我在C#项目中引用的DLL如下:
[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin, string cout, string flimit,
string frate, string fwindow, string fincrement, string fbird,
string fparameter, string fvalidation, string fcoupon);
FeeCalculation函数在DLL中的导出如下:
extern "C" __declspec(dllexport) void __stdcall FeeCalculation(char *cin,
char *cout, char *flimit, char *frate,
char *fwindow, char *fincrement, char *fbird,
char *fparameter, char *fvalidation, char *fcoupon);
DLL函数以char *的形式返回对其内部结构的引用,因此,如果要在C ++中引用此DLL,则可以执行以下操作进行计算并获取返回的结构:
FeeCalculation(buff, (char *)&fans, (char *)fl, (char *)ft, (char *)fw, (char *)fi, (char *)fe, (char *)&fm, (char *)val, (char *)cpn);
现在,如何使用C#检索通过引用返回的那些值? 意思是,我该如何在C#中执行相同的操作来获取返回的结构以获取返回的计算结果? 我知道我需要创建一个不安全的方法,但是我不清楚如何像在C ++中那样处理C#中的内存地址。
编辑:下面说明要使用IntPtr,但是如何将其放入相同的结构中,以便可以引用结构的字段?
编辑:这是我感兴趣的返回结构(cout):
struct feeAnswer {
unsigned int fee;
unsigned int tax1;
unsigned int tax2;
unsigned int tax3;
unsigned int tax4;
unsigned int surcharge1;
unsigned int surcharge2;
unsigned int validationFee;
unsigned int couponFee1;
unsigned int couponFee2;
unsigned int couponFee3;
unsigned int couponFee4;
unsigned short int dstay; //Day Stay
unsigned short int mstay; //Minute Stay
};
这是我将与其他结构一起传递的(cin)(目前它们为零字节,我想先使其工作,然后再实现其余部分):
struct feeRequest {
unsigned char day;
unsigned char month;
unsigned int year; //2000 ~ 2099
unsigned char hour;
unsigned char minute;
unsigned char rate;
unsigned char validation;
unsigned char coupon1;
unsigned char coupon2;
unsigned char coupon3;
unsigned char coupon4;
};
在这种情况下,char *参数不是字符串,而是指向表示数据的原始字节块的指针。 您应该将参数编组为IntPtr类型的实例,并与Marshal.AllocHGlobal一起创建一个内存块,然后与Marshal.PtrToStructure一起将该内存块转换为可用的.NET类型。
举个例子:
[StructLayout(LayoutKind.Sequential)]
struct MyUnmanagedType
{
public int Foo;
public char C;
}
IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyUnmanagedType)));
try
{
FeeCalculation(memory);
MyUnmanagedType result = (MyUnmanagedType)Marshal.PtrToStructure(
memory, typeof(MyUnmanagedType));
}
finally
{
Marshal.FreeHGlobal(memory);
}
编辑:现在我们有了可以使用的结构,可能有更好的解决方案。 只需在C#中声明与您的C ++结构匹配的结构,然后在extern声明中使用它们即可
[StructLayout(LayoutKind.Sequential)]
public struct feeAnswer {
public uint fee;
public uint tax1;
public uint tax2;
public uint tax3;
public uint tax4;
public uint surcharge1;
public uint surcharge2;
public uint validationFee;
public uint couponFee1;
public uint couponFee2;
public uint couponFee3;
public uint couponFee4;
public ushort dstay; //Day Stay
public ushort mstay; //Minute Stay
};
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct feeRequest {
public byte day;
public byte month;
public uint year; //2000 ~ 2099
public byte hour;
public byte minute;
public byte rate;
public byte validation;
public byte coupon1;
public byte coupon2;
public byte coupon3;
public byte coupon4;
};
[DllImport ("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern void FeeCalculation (
feeRequest cin,
out feeAnswer cout,
...
....
原始答案(在使用结构之前)
在我看来,这些不是对内部字符串的引用,而是对将由调用填充的字符串缓冲区的指针。 如果要返回字符串指针,则将其声明为char**
而不是char*
。
因此,我认为这些只是标准输出参数。 只有很多。 所以您的C#互操作看起来像这样
[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin,
[MarshalAs(UnmanagedType.LPStr, SizeConst=100)]
out string cout,
[MarshalAs(UnmanagedType.LPStr, SizeConst=100)]
out string flimit,
或如果您的“字符串”不是真正的字符串
[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin,
[MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
out byte[] cout,
[MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
out byte[] flimit,
....
要回答您的Edit,您需要创建一个结构,然后在字段上使用StructLayoutAttribute来使字节顺序和填充与原始dll相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.