我正试图使用一个结构数组将数据传递到/从我的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");
    }
}

最佳答案

你走的方向是对的您只需要在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;
            }
        }
    }
}

关于c# - 使用pinvoke将struct数组内的C struct的嵌入式数组传递给C#,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11946895/

10-11 22:46
查看更多