将结构从c#传递到c dll

将结构从c#传递到c dll,c#,c,pinvoke,structure,C#,C,Pinvoke,Structure,我正在努力学习足够多的C#,以便通过引用C DLL来传递结构;但它永远不会到达“cFunction”。正如您在cFunction中看到的,我显式地将streamSubset值设置为44;但在c#部分,它不会返回“44”。 下面是C代码: typedef struct s_mPlot { double price[100]; int streamSubset; } mPlot; extern "C" __declspec( dllexport ) v

我正在努力学习足够多的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代码


}

尝试明确指定调用约定:

 [DllImport("C:\\Users\\joe\\mcDll.dll", CallingConvention=CallingConvention.Cdecl CharSet = CharSet.Auto)]

默认情况下,VC使用调用约定
cdecl
导出,但默认情况下
DllImport
使用
stdcall
。因此,您必须明确指定其中至少一个,或者更好地同时指定两个

尝试显式指定调用约定:

 [DllImport("C:\\Users\\joe\\mcDll.dll", CallingConvention=CallingConvention.Cdecl CharSet = CharSet.Auto)]

默认情况下,VC使用调用约定
cdecl
导出,但默认情况下
DllImport
使用
stdcall
。因此,您必须明确指定其中至少一个,或者更好地同时指定两个

[In,marshallas(UnmanagedType.LPStruct)]
替换为
ref
[In,marshallas(UnmanagedType.LPStruct)]
替换为
ref

我可以看到以下内容:

  • 您几乎肯定需要在
    DllImport
    属性中指定
    cdecl
    调用约定。添加
    CallingConvention=CallingConvention.Cdecl
  • 我认为
    UnmanagedType.LPStruct
    增加了额外的间接寻址级别。但是您正在传递一个C#
    ,它是一个引用类型。这意味着您正在将一个指针传递给一个指针。这是一个层次的间接太多。首先,一起删除
    [In,marshallas(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
    );
    

    我可以看到:

  • 您几乎肯定需要在
    DllImport
    属性中指定
    cdecl
    调用约定。添加
    CallingConvention=CallingConvention.Cdecl
  • 我认为
    UnmanagedType.LPStruct
    增加了额外的间接寻址级别。但是您正在传递一个C#
    ,它是一个引用类型。这意味着您正在将一个指针传递给一个指针。这是一个层次的间接太多。首先,一起删除
    [In,marshallas(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
    );
    

    请提供更多信息——你看到了什么?崩溃意外的结果?数据不正确?你试过调试它吗?C代码无法使用调试器运行。很长的解释,但这是一个商业产品,阻止它。请提供更多信息-你看到了什么?崩溃意外的结果?数据不正确?你试过调试它吗?C代码无法使用调试器运行。很长的解释,但这是一个商业产品阻止了它。尝试添加它,我得到了一个神秘的消息(来自商业产品,而不是vs2010):“对象引用未设置为对象的实例”@user994179,这很奇怪。然后我认为你需要在你的C++ DLL上使用STDCLAK。试着添加这个,我得到这个神秘消息(来自商业产品,而不是VS2010):“对象引用没有设置到对象的实例”@ USER44179,这很奇怪。然后我认为您需要在C++ DLL上使用STDCALL。OK,所以它现在读到:“public static ExtEngultCultCube(REF MPLOT MPGOT)”,我还必须在调用CcOffice:“cFrof(REF MPLOT)”的PARAM列表中添加“REF”关键字。仍然是相同的错误:“Object ref未设置为对象的实例。”好的,现在它的内容是:“public static extern void cFunction(ref-MPLOT-MPLOT)”,我还必须将“ref”关键字添加到参数列表中,在该列表中我调用cFunction:“cFunction(ref-MPLOT)”。还是同样的错误:“对象引用未设置为对象的实例。”不,您的建议也不起作用。在搜索了几十页之后,我找不到任何关于这个的例子。开始认为它不能完成。这个答案中的代码与你的问题中的C++代码非常匹配。自己编写一个C++的DLL证明是这样的。有些我们看不到的地方出了问题。你要做的是,封送这个结构非常容易实现。我按照你的建议做了,你是对的。我发现第三方应用程序中有一个bug导致了这个问题。谢谢你的帮助。不,你的建议也不起作用。在搜索了几十页之后,我找不到任何关于这个的例子。开始认为它不能完成。这个答案中的代码与你的问题中的C++代码非常匹配。自己编写一个C++的DLL证明是这样的。有些我们看不到的地方出了问题。你要做的是,封送这个结构非常容易实现。我按照你的建议做了,你是对的。我发现第三方应用程序中有一个bug导致了这个问题。谢谢你的帮助。