AccessViolationException в вызове функции PInvoke с двойными массивами и пустыми указателями

Я хочу вызвать две функции из DLL с чистым C-интерфейсом через PInvoke со следующими сигнатурами:

void *pj_init_plus(const char *srsName);
int pj_datum_transform(void *src, void *dst, long point_count, int point_offset,
                    double *x, double *y, double *z );

Пинвок методы:

[DllImport("proj.dll", CallingConvention = CallingConvention.Cdecl, 
    EntryPoint = "pj_init_plus", CharSet = CharSet.Ansi)]
public static extern IntPtr PjInit(string srsName);

[DllImport("proj.dll", EntryPoint = "pj_transform", CallingConvention =
    CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int PjTransformation(IntPtr src, IntPtr dst,long pointCount,
    int pointOffset, double[] x, double[] y,double[] z);

В моем C#-коде я вызываю методы:

IntPtr pjSrc = PjInit("+proj=longlat +datum=WGS84 +no_defs");
IntPtr pjDst = PjInit("+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs");

double[] x = { 4489580.7, 4489580.7 };
double[] y = { 5320767.7, 5320767.7 };
double[] z = { 0.0, 0.0};

PjTransformation(pjSrc, pjDst, x.Length, 1, x, y, z);

Вызов PjInit работает нормально и возвращает действительный указатель. Но вызов PjTransformation вызывает исключение AccessViolationException. Я думаю, что есть проблема с двойными массивами. В одном сообщении упоминалось, что clr-массив уже совместим с собственным массивом и не требует сортировки вручную. Я также попробовал это с атрибутом [MarshalAs(UnmanagedType.LPArray)] для двойных массивов, но это не помогло. Или может возникнуть исключение из структуры, которая возвращается в виде указателей void из первого вызова функции. Проблема в том, что я не знаю тип структуры.

Функции dll в порядке, я попробовал это с собственным кодом C, и это сработало. Также параметр pointOffset не мог вызвать исключение.


person hmMT    schedule 10.10.2013    source источник
comment
Пробовали ли вы проверять свои гипотезы, создавая оболочки вокруг методов C? т.е. создайте метод C, который возвращает void вместо структуры, и p/вызовите это. Если это работает, то проблема заключается в структуре, и вы можете ее отладить. Если это все еще не удается, создайте перегрузку, которая не принимает двойные массивы, и повторите попытку.   -  person Patrick Quirk    schedule 10.10.2013


Ответы (1)


Ваше объявление P-invoke выглядит хорошо и правильно. Единственная проблема, о которой я могу думать, заключается в том, что исключение AV выдается из самой нативной функции, а не при маршалинге.

Я советую вам попытаться отладить код с помощью собственного отладчика, вы сможете определить точную строку кода, где возникает исключение, и диагностировать, возникает ли проблема во время сортировки или фактического выполнения функции.

person David Dor    schedule 10.10.2013