C # / C ++ interop - нужна помощь в определении моей структуры данных - PullRequest
4 голосов
/ 02 октября 2009

Я работаю над приложением C #, которое пытается использовать функциональность, предоставляемую через C ++ DLL. Я испытываю трудности с получением определений DLLImport, которые работают в данный момент.

Вот часть уравнения C ++:

struct Result
{
    FLOAT   first;
    FLOAT   second;
};

struct ResultData
{
    UINT            uint1;
    UINT            uint2;
    Result          result;
    Result*         pResults;
};

#define DllImport __declspec(dllimport)    
extern "C"
{
    DllImport HRESULT APIENTRY Process(const PCWSTR FileName, const PCWSTR logfileFileName, const PCWSTR DataFileName, ResultData** ppResults);
    DllImport HRESULT APIENTRY Release(ResultData* pResults);
}

На стороне C # вот что я сделал до сих пор:

    [StructLayout(LayoutKind.Sequential)]
    public struct Result
    {
        public float first;
        public float second;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct ResultData
    {
        public uint uint1;
        public uint uint2;
        public Result result;
        public Result[] Results;
    }    

        DllImport("MyDLL.dll")]
        static extern uint Release(ResultData pResults);

        [DllImport("MyDLL.dll")]
        static extern uint Process(string FileName, string logfileFileName, string DataFileName, ref ResultData ppResults);

Это правильный способ сделать это? Больше всего меня беспокоит то, что pResults является членом структуры ResultData. Я не хочу, чтобы это копировалось по значению, поскольку это будет большой объем данных, и я не хочу дублировать память ... как я могу убедиться, что этого не произойдет?

Я ценю вашу помощь.

Ответы [ 2 ]

5 голосов
/ 02 октября 2009

Самая насущная проблема, которая у меня возникает, - это член Results в ResultData. Нативный тип - Result*, но вы перевели его как массив. Это может или не может работать (не могу вспомнить из головы). Что будет работать, так это маршалинг как тип IntPtr.

[StructLayout(LayoutKind.Sequential)]
public struct ResultData
{
    public uint uint1;
    public uint uint2;
    public Result result;
    public IntPtr RawResults;
    public Result Results { get { return (Result)Marshal.PtrToStructure(RawResults,typeof(Result)); }
} 

Предполагается, что это одно значение. Если это более одного значения, потребуется более сложная сортировка.

Также нативный метод Release принимает ResultData*, но у вас есть простой по значению тип ResultData в управляемой подписи. Он должен иметь такой же уровень косвенности. Вы можете добиться этого, сделав это ref param.

DllImport("MyDLL.dll")]
static extern uint Release(ref ResultData pResults);
0 голосов
/ 02 октября 2009

Если вы можете сохранить интерфейс для чистых примитивных типов C, вам не придется выполнять сортировку. Это избавит вас от душевных страданий.

...