2

構造体の配列を使用して、C# ui および C dll との間でデータをやり取りしようとしています。さらに複雑なのは、構造体に別の構造体配列が含まれていることです。pinvoke を使用してより単純なものを作成する方法を理解しましたが、埋め込まれた構造をどのように宣言し、どのように渡すのですか?

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class csForm {
    public int endDate;   
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public char[] formId;
}

 [DllImport("myDll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
 public static extern void fillForm([In, Out] csForm data, 5);

// c code
typedef struct s_ptxRow {
int ptxNumber;
char primitive[128];
int primitiveParams[128];
} ptxRow;

typedef struct s_workSpace{
char formId[128];
int endDate;
ptxRow PtxRow[128];
} cForm;

extern "C" __declspec(dllexport) fillForm(cForm csForm[], interface csFormCount)
{

    for (int i = 0, j = 0; i < csFormCount; ++i)
    {
        j = int / 2;
        csForm[i].endDate = i;
        strcpy(csForm[i].formId, "formId here");

        csForm[i].PtxRow[j].ptxNumber = i;
        csForm[i].PtxRow[j].primitiveParams[i] = i;
        strcpy(csForm[i].PtxRow[j].primitive, "someText");
    }
}
4

1 に答える 1

0

あなたは正しい方向に進んでいました。C# で構造体を宣言し、ptxRowその配列を に追加するだけで済みcsFormます。事前に配列を割り当てる必要さえありません - どうやら P/Invoke が配列のサイズを知っているので、配列を割り当ててくれるようです。一部の宣言に微細な誤りがあったため、サンプル コード全体を含めます。

注: C# でクラスを使用しようとすると、奇妙な結果 (たとえば、C++ コードのメンバーとポインターの値が正しくない) が発生し、さまざまなエラーが発生しました。構造体に切り替えると、問題が解消されました。これは参照型と値型に関係があると思いますが、より知識のある人からの意見をいただければ幸いです。問題がある場合は、.NET 3.5 でテストしています。

#include <string.h>

typedef struct s_ptxRow {
    int ptxNumber;
    char primitive[128];
    int primitiveParams[128];
} ptxRow;

typedef struct s_workSpace {
    char formId[128];
    int endDate;
    ptxRow PtxRow[128];
} cForm;

extern "C" __declspec(dllexport) void fillForm(cForm csForm[], int csFormCount)
{
    for (int i = 0, j = 0; i < csFormCount; ++i)
    {
        j = i / 2;
        csForm[i].endDate = i;
        strcpy(csForm[i].formId, "formId here");

        csForm[i].PtxRow[j].ptxNumber = i;
        csForm[i].PtxRow[j].primitiveParams[i] = i;
        strcpy(csForm[i].PtxRow[j].primitive, "someText");
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace PInvokeStructsCS
{
    class Program
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct PtxRow
        {
            public int ptxNumber;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
            public char[] primitive;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
            public int[] primitiveParams;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct csForm
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
            public char[] formId;
            public int endDate;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
            public PtxRow[] ptxRow;
        }

        [DllImport("PInvokeStructsC.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public static extern void fillForm([In, Out]csForm[] data, int count);

        static void Main(string[] args)
        {
            csForm[] forms = new csForm[2];

            try
            {
                fillForm(forms, 2);
            }
            catch (Exception e)
            {
                Console.Out.WriteLine(e.Message);
                return;
            }
        }
    }
}
于 2012-09-04T17:29:22.047 に答える