1

C DLLを参照して構造を渡すことができるように、十分なC#を学習しようとしています。しかし、それは「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();  
    }

}

}

4

3 に答える 3

1

次のことがわかります。

  1. ほとんどの場合cdecl、属性で呼び出し規約を指定する必要がありDllImportます。を追加しCallingConvention=CallingConvention.Cdeclます。
  2. UnmanagedType.LPStructこれにより、さらにレベルの高い間接性が追加されると思います。classしかし、参照型であるC# を渡しています。つまり、ポインターをポインターに渡します。これは、1 レベルの間接化が多すぎることです。まずは全削除[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
);
于 2012-07-03T12:14:32.717 に答える
0

に置き換え[In, MarshalAs(UnmanagedType.LPStruct)]ますref

于 2012-07-03T06:44:19.297 に答える
0

呼び出し規約を明示的に指定してみてください。

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

cdeclVC はデフォルトで呼び出し規約を使用してエクスポートしますが、デフォルトでDllImport使用stdcallします。そのため、少なくとも 1 つ、またはできれば両方を明示的に指定する必要があります。

于 2012-07-03T06:34:46.980 に答える