簡體   English   中英

返回從c ++到c#的指針數組

[英]Return array of pointers from c++ to c#

下面我有一個來自c ++的代碼片段。 我需要返回指針數組(到TempStruct)。

問題是在c#側我只得到一個元素。 另一方面,我得到AV。

**C++**
extern "C" __declspec(dllexport) void GetResult(TempStruct** outPtr, long *size)
{       
    *outPtr = (TempStruct*)new TempStruct*[2];

     outPtr[0] = new TempStruct("sdf", 123);
     outPtr[1] = new TempStruct("abc", 456);

    *size = 2;      
}

**C#**    
[DllImport("test.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void GetResult(out IntPtr outPtr, out int size);

IntPtr ptr = IntPtr.Zero;
int length;        
GetResult(out ptr, out length);

int size = Marshal.SizeOf(typeof(TempStruct));
TempStruct[] someData2 = new TempStruct[length];

for (int i = 0; i < length; i++)
{
   IntPtr wskptr = (IntPtr)(ptr.ToInt64() + (size * i));
   someData2[i] = (TempStruct)Marshal.PtrToStructure(wskptr, typeof(TempStruct));            
} 

你做錯了。

你正在混合指針類型。

通過使用new TempStruct()您將創建一個指向TempStruct的指針數組。 我給你的例子創建了一個TempStruct數組。 看到不同?

現在...... TempStruct** outPtr應該是TempStruct*** outPtr (因為你想返回( * )一個數組( * )指針( * )...或者TempStruct**&如果你願意:-)

改變這一行

someData2[i] = (TempStruct)Marshal.PtrToStructure(Marshal.ReadIntPtr(wskptr), typeof(TempStruct));

因為你必須閱讀單指針。

我希望你刪除各種TempStruct並使用刪除

delete[] ptr;

運算符刪除結構數組。

完整示例:

C ++:

struct TempStruct
{
    char* str;
    int num;

    // Note the strdup. You don't know the source of str.
    // For example if the source is "Foo", then you can't free it.
    // Using strdup solves this problem.
    TempStruct(const char *str, int num) 
        : str(strdup(str)), num(num)
    {
    }

    ~TempStruct()
    {
        free(str);
    }
};

extern "C"
{
    __declspec(dllexport) void GetResult(TempStruct ***outPtr, int *size)
    {
        *outPtr = new TempStruct*[2];

        (*outPtr)[0] = new TempStruct("sdf", 123);
        (*outPtr)[1] = new TempStruct("abc", 456);

        *size = 2;
    }

    __declspec(dllexport) void FreeSomeData(TempStruct **ptr, int size)
    {
        for (int i = 0; i < size; i++)
        {
            delete ptr[i];
        }

        delete[] ptr;
    }
}

C#:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1), Serializable]
internal struct TempStruct
{
    public string str;
    public int num;
}

[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern void GetResult(out IntPtr outPtr, out int numPtr);

[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void FreeSomeData(IntPtr ptr, int num);

// C++ will return its TempStruct array in ptr
IntPtr ptr;
int size;

GetResult(out ptr, out size);

TempStruct[] someData2 = new TempStruct[size];

for (int i = 0; i < size; i++)
{
    IntPtr ptr2 = Marshal.ReadIntPtr(ptr, i * IntPtr.Size);
    someData2[i] = (TempStruct)Marshal.PtrToStructure(ptr2, typeof(TempStruct));
}

// Important! We free the TempStruct allocated by C++. We let the
// C++ do it, because it knows how to do it.
FreeSomeData(ptr, size);

請注意,C# struct上不需要[Serializable]Pack=1

更正確的C ++:

__declspec(dllexport) void GetResult(TempStruct **&outPtr, int &size)
{
    outPtr = new TempStruct*[2];

    outPtr[0] = new TempStruct("sdf", 123);
    outPtr[1] = new TempStruct("abc", 456);

    size = 2;
}

它更正確,因為outPtrsize都不能為NULL 請參閱https://stackoverflow.com/a/620634/613130 C#簽名是一樣的。

C ++代碼是錯誤的。 它返回一個指向struct的指針數組。 你轉換new返回的值的事實應該提醒你你犯了一個錯誤的事實。 您想要返回一個struct數組。

它應該是:

*outPtr = new TempStruct[2];
(*outPtr)[0].str = "sdf";
(*outPtr)[0].i = 123;
(*outPtr)[1].str = "abc";
(*outPtr)[1].i = 456;
*size = 2;      

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM