将C ++非托管代码转换为C#

时间:2022-09-01 09:51:48

I am trying to get below working C++ DLL code in C# using Marshal. It has two structures which are passed as pointer parameters in the API which is exported, but the structure response values it is giving out in C# is not in correct sequence. Whereas it is working fine in VC++.

我试图使用Marshal在C#中使用C ++ DLL代码。它有两个结构作为导出的API中的指针参数传递,但它在C#中给出的结构响应值的顺序不正确。虽然它在VC ++中运行良好。

//C++ Code - Working
//Structure 1
typedef struct
{
    bool    bExist;
    bool    bAvailable;
    int     iNoteNumber;
    int     iDispenseNumber;
    int     iOutNoteNumber;
    char    cStatus;
    char    acBoxID[6];
} tHopperStatus;
//Structure 2
typedef struct 
{
    char acCurrency[4]; 
    int lDenomination;  
    int iRemainCount;   
    int iCount; 
    int iOutCount;
    int iRejectCount;
    int iPurgeCount;    
    BYTE    byHopper;
    char    cStatus;
    char    cLastStatus;    
    char    acBoxID[6];
    BYTE    byBoxType;
    char    acReserved1[10];
    char    acReserved2[10];
    int iReserverd1;
    int iReserverd2;
} tCashBox;
//API using above two structures
int iGetCassette(tCashBox* p_psCashBox,tDevReturn* p_psStatus);

//Calling API by passing pointer of Structure Array  
tCashBox l_asBox[8] = {0};
tDevReturn l_asReturn[8] = {0};
int l_iRes = l_pDev->iGetCassette(l_asBox, l_asReturn);

What I implemented in C#:

我在C#中实现的:

//C# Code
//Structure 1
[StructLayout(LayoutKind.Sequential)]
unsafe public struct tDevReturn
{
    public tDevReturn(int param)
    {
        iLogicCode = 0;
        iPhyCode = 0;
        iHandle = 0;
        iType = 0;
        acDevReturn = new char[128];
        acReserve = new char[128];
    }
    public int iLogicCode;
    public int iPhyCode;
    public int iHandle;
    public int iType;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public char[] acDevReturn;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public char[] acReserve;
}
//Structure 2
[StructLayout(LayoutKind.Sequential)]
unsafe public struct tCashBox
{
    public tCashBox(int param)
    {
        acCurrency = new char[4];
        lDenomination = 0;
        iRemainCount = 0;
        iCount = 0;
        iOutCount = 0;
        iRejectCount = 0;
        iPurgeCount = 0;
        byHopper = 0;
        cStatus = '\0';
        cLastStatus = '\0';
        acBoxID = new char[6];
        byBoxType = 0;
        acReserved1 = new char[10];
        acReserved2 = new char[10];
        iReserverd1 = 0;
        iReserverd2 = 0;
    }
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public char[] acCurrency;
    public long lDenomination;
    public int iRemainCount;
    public int iCount;
    public int iOutCount;
    public int iRejectCount;
    public int iPurgeCount;
    public byte byHopper;
    public char cStatus;
    public char cLastStatus;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
    public char[] acBoxID;
    public byte byBoxType;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
    public char[] acReserved1;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
    public char[] acReserved2;
    public int iReserverd1;
    public int iReserverd2;
}

//API Import Declaration
[DllImport("xxxxxxxxxx.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int CDM_iGetCassette([In, Out] tCashBox[] p_psCashBox, [In, Out] tDevReturn[] p_psStatus);

//API Call - but filling up the structure array with random values and incorrect sequence
tDevReturn[] response = new tDevReturn[8];
tCashBox[] cashboxData = new tCashBox[8];
int ret = Wrapper.CDM_iGetCassette(cashboxData, response);

I have a doubt, whether passing Array of Structure in this way is allowed or not in C#, where as in C++ it is working. If someone can help me in this would be a great help. Thanks in advance.

我怀疑,在C#中是否允许以这种方式传递Array of Structure,就像在C ++中一样。如果有人可以帮助我,这将是一个很大的帮助。提前致谢。

EDIT : I changed data type of 'lDenomination' from long to int. Now, the array first element is getting filled up properly. But the remaining seven element of struct array are not getting filled up.

编辑:我将'lDenomination'的数据类型从long更改为int。现在,数组第一个元素正在填满。但结构数组的剩余七个元素没有被填满。

If someone can help me, How to create Structure Array with all elements having memory in sequence.

如果有人可以帮助我,如何使用所有具有内存顺序的元素创建结构数组。

1 个解决方案

#1


0  

Solved the issue finally with below updated Structure 2: 1. Changed data type of 'lDenomination' from long to int. 2. Added Pack=1 and CharSet=CharSet.Ansi in struct layout parameters.

最后通过以下更新的结构2解决了这个问题:1。将'lDenomination'的数据类型从long更改为int。 2.在struct layout parameters中添加了Pack = 1和CharSet = CharSet.Ansi。

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct tCashBox
{
    public tCashBox(int param)
    {
        acCurrency = new char[4];
        lDenomination = 0;
        iRemainCount = 0;
        iCount = 0;
        iOutCount = 0;
        iRejectCount = 0;
        iPurgeCount = 0;
        byHopper = 0;
        cStatus = '\0';
        cLastStatus = '\0';
        acBoxID = new char[6];
        byBoxType = 0;
        acReserved1 = new char[10];
        acReserved2 = new char[10];
        iReserverd1 = 0;
        iReserverd2 = 0;
    }
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public char[] acCurrency;
    public int lDenomination;
    public int iRemainCount;
    public int iCount;
    public int iOutCount;
    public int iRejectCount;
    public int iPurgeCount;
    public byte byHopper;
    public char cStatus;
    public char cLastStatus;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
    public char[] acBoxID;
    public byte byBoxType;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
    public char[] acReserved1;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
    public char[] acReserved2;
    public int iReserverd1;
    public int iReserverd2;
}

#1


0  

Solved the issue finally with below updated Structure 2: 1. Changed data type of 'lDenomination' from long to int. 2. Added Pack=1 and CharSet=CharSet.Ansi in struct layout parameters.

最后通过以下更新的结构2解决了这个问题:1。将'lDenomination'的数据类型从long更改为int。 2.在struct layout parameters中添加了Pack = 1和CharSet = CharSet.Ansi。

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct tCashBox
{
    public tCashBox(int param)
    {
        acCurrency = new char[4];
        lDenomination = 0;
        iRemainCount = 0;
        iCount = 0;
        iOutCount = 0;
        iRejectCount = 0;
        iPurgeCount = 0;
        byHopper = 0;
        cStatus = '\0';
        cLastStatus = '\0';
        acBoxID = new char[6];
        byBoxType = 0;
        acReserved1 = new char[10];
        acReserved2 = new char[10];
        iReserverd1 = 0;
        iReserverd2 = 0;
    }
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public char[] acCurrency;
    public int lDenomination;
    public int iRemainCount;
    public int iCount;
    public int iOutCount;
    public int iRejectCount;
    public int iPurgeCount;
    public byte byHopper;
    public char cStatus;
    public char cLastStatus;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
    public char[] acBoxID;
    public byte byBoxType;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
    public char[] acReserved1;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
    public char[] acReserved2;
    public int iReserverd1;
    public int iReserverd2;
}