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

你正朝着正确的方向前进。您只需要ptxRow在 C# 中声明该结构,然后将其数组添加到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 回答