我正在尝试学习足够的C#,以便通过引用C DLL传递一个结构;但它永远不会到达“cFunction”。正如您在cFunction中看到的,我明确地将streamSubset值设置为44;但回到c#部分,它不会返回“44”。 这是C代码:
typedef struct s_mPlot
{
double price[100];
int streamSubset;
} mPlot;
extern "C" __declspec( dllexport )
void cFunction(mPlot *Mplot){
Mplot->streamSubset = 44;}
//这里是c#代码
using System;
using Vibe.Function;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public class MPLOT
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public double [] price;
public int streamSubset;
}
namespace Vibe.Indicator{
public class myIdx : IndicatorObject {
[DllImport("C:\\Users\\joe\\mcDll.dll", CharSet = CharSet.Auto)]
public static extern void cFunction(
[In, MarshalAs(UnmanagedType.LPStruct)] MPLOT mPlot );
public myIdx(object _ctx):base(_ctx){}
private IPlotObject plot1;
protected override void Create()
{
MPLOT mPlot = new MPLOT();
mPlot.streamSubset = 2;
cFunction(mPlot);
if (mPlot.streamSubset == 44)
go();
}
}
}
答案 0 :(得分:1)
我可以看到以下内容:
cdecl
属性中指定DllImport
调用约定。添加CallingConvention=CallingConvention.Cdecl
。UnmanagedType.LPStruct
增加了额外的间接水平。但是你传递的是一个引用类型的C#class
。这意味着您正在将指针传递给指针。这是间接的一个层次太多了。首先完全删除[In, MarshalAs(UnmanagedType.LPStruct)]
。然后你的代码应该工作。如果您切换到结构而不是MPLOT
的类,那么您需要通过ref
来获取间接。我想我会得到这样的代码:
[StructLayout(LayoutKind.Sequential)]
public struct MPLOT
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public double [] price;
public int streamSubset;
}
[DllImport("dllname.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern void cFunction(
ref MPLOT mPlot
);
答案 1 :(得分:0)
尝试明确指定调用约定:
[DllImport("C:\\Users\\joe\\mcDll.dll", CallingConvention=CallingConvention.Cdecl CharSet = CharSet.Auto)]
默认情况下, VC导出调用约定为cdecl
,但DllImport
默认使用stdcall
。因此,您必须明确地或更好地指定它们中的至少一个。
答案 2 :(得分:0)
将[In, MarshalAs(UnmanagedType.LPStruct)]
替换为ref
。