2

インターフェイスを持つDLLがあります

struct modeegPackage
{
    uint8_t     version;    // = 2
    uint8_t     count;      // packet counter. Increases by 1 each packet
    uint16_t    data[6];    // 10-bit sample (= 0 - 1023) in big endian (Motorola) format
    uint8_t     switches;   // State of PD5 to PD2, in bits 3 to 0
};

__declspec(dllexport) void __cdecl initSerial();

__declspec(dllexport) void __cdecl closeSerialPort();

__declspec(dllexport) struct modeegPackage __cdecl getPackage();

そしてC#アダプター

class EEGCommunication
{
    [StructLayout(LayoutKind.Sequential)]
    public struct modeegPackage
    {

        /// unsigned char
        public byte version;

        /// unsigned char
        public byte count;

        /// unsigned int[6]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.U2)]
        public UInt16[] data;

        /// unsigned char
        public byte switches;
    }

    private const string DLL = "libneureader-lib.dll";

    [DllImport(DLL, EntryPoint = "_Z10initSerialv")]
    public static extern void InitSerial();

    [DllImport(DLL, EntryPoint = "_Z15closeSerialPortv")]
    internal static extern void CloseSerialPort();

    [DllImport(DLL, EntryPoint = "_Z10getPackagev", CallingConvention = CallingConvention.Cdecl)]
    public static extern modeegPackage GetPackage();
}

GetPackageしかし、メソッドを呼び出そうとすると、エラーが発生しますMethod's type signature is not PInvoke compatible.

コードの何が問題になっていますか?

更新: コードが更新されました

4

2 に答える 2

0

問題を引き起こしているのはアレイです。pinvoke マーシャラーは、関数の戻り値として構造体を値で返すという特定のケースでそれを処理するのが好きではありません。これは一般的に面倒です。これを行う方法は、コンパイラに大きく依存します。GCCを使用しているように聞こえるので、問題が発生する可能性が高いです。これは通常、呼び出し元がスタック上の戻り値にスペースを割り当て、ポインターを渡すことによって行われます。

大雑把ですが効果的なトリックは、配列を自分で拡張することです。要素が 6 つしかないため、十分に実用的です。次のように配列を置き換えます。

        /// unsigned int[6]
        public short data0;
        public short data1;
        //...
        public short data5;

これは例外を解決します。データが正しく取得されるかどうかはまだわかりません。そうでない場合は、MSVC に切り替える必要があるかもしれません。

于 2012-12-09T15:38:55.117 に答える