Передача указателя на массив из C# в c DLL - PullRequest
1 голос
/ 05 мая 2020

У меня есть dll, у которой есть аргументы с двойным *, например xyz (double * a, double * b). Я использую эту DLL для передачи двух двойных массивов функции xyz. Проблема в том, что когда я передаю двойной массив по ссылке с помощью a, массив обновляется, но значения округляются, что происходит, когда вы приводите что-то к типу int и от него. Не могли бы вы рассказать мне, как эффективно отправить этот двойной массив в c dll и получить желаемый результат в десятичном формате. (Смена DLL не вариант). Также я попробовал Marshal, я не совсем уверен, правильно ли я поступил, но всякий раз, когда я менял аргумент xyz на xyz (IntPtr a, double * b) или что-то, что я использовал, чтобы получить AccessViolationException, поврежденная память.

Ответы [ 2 ]

0 голосов
/ 05 мая 2020

Попробуйте следующее:

            double[] a = { 1.23, 2.34, 5.45 };
            IntPtr aptr = Marshal.AllocHGlobal(a.Length * sizeof(double));
            Marshal.Copy(a, 0, aptr, a.Length);
            double[] b = { 1.23, 2.34, 5.45 };
            IntPtr bptr = Marshal.AllocHGlobal(b.Length * sizeof(double));
            Marshal.Copy(b, 0, bptr, b.Length);

            xyz(aptr, bptr)
0 голосов
/ 05 мая 2020

Если я правильно понимаю, вы передаете массив от C# до C (или C ++) кода. Проблема с подходом к отправке массива напрямую методу, подобному xyz(double* a, double* b), заключается в том, что код не может знать размеры массивов. Это может привести к исключениям нарушения прав доступа, если код C / C ++ пытается получить доступ к элементу, который находится за пределами массива.

Есть несколько способов обойти это - либо с помощью SafeArray из C# ( который уже содержит атрибут размера), отправив массивы в некоторый метод связывания с размерами или передав данные в структуре, например:

internal struct ArraysStruct
{
    public int floatArraySize;
    public IntPtr floatArray;
    public int uintArraySize;
    public IntPtr uintArray; 
}

Что затем будет сопоставлено на стороне C / C ++ что-то вроде:

typedef struct ArraysStruct
{
    size_t floatArraySize;
    float* floatArray;
    size_t uintArraySize;
    unsigned int* uintArray;
}

Вам нужно будет использовать Marshal.AllocHGlobal(), чтобы сначала распределить массивы по размерам (в C#), а затем Marshal.FreeHGlobal(), когда вы закончите с ними.

...