将结构从c#传递给C dll

时间:2012-07-03 06:28:11

标签: 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 )  
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();  
    }

}

}

3 个答案:

答案 0 :(得分:1)

我可以看到以下内容:

  1. 您几乎肯定需要在cdecl属性中指定DllImport调用约定。添加CallingConvention=CallingConvention.Cdecl
  2. 我相信UnmanagedType.LPStruct增加了额外的间接水平。但是你传递的是一个引用类型的C#class。这意味着您正在将指针传递给指针。这是间接的一个层次太多了。首先完全删除[In, MarshalAs(UnmanagedType.LPStruct)]。然后你的代码应该工作。如果您切换到结构而不是MPLOT的类,那么您需要通过ref来获取间接。
  3. 我想我会得到这样的代码:

    [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