2015-01-09 4 views
0

Я пытаюсь вернуть указатель из моей C++ dll в C#. Я пробовал все, но мой указатель типа double не имеет значения.Как вернуть двойной указатель из C++ dll в C#?

Ниже мой импорт DLL C++:

[DllImport("/Resources/libfli.dll", EntryPoint = "FLIGetTemperature")] 
public static extern unsafe int FLIGetTemperature(long dev, double* temperature); 
// Get the temperature of a given camera. This function places the temperature of the CCD camera 
// cold finger of device dev in the location pointed to by temperature. 
// Return Value: Zero on success. Non-zero on failure. 
// Parameters: dev Camera device to get the temperature of. 
// temperature Pointer to where the temperature will be placed. 
// See Also: FLISetTemperature 

Defination из FliGetTemperatre от FLI_SDK_Documentation

LIBFLIAPI FLIGetTemperature (flidev_t dev, double* temperature) 
Get the temperature of a given camera. 

Ниже, как я объявляю свой призыв к .dll в C#:

unsafe public void GetTheTemperatureOfTheCamera() 
{ 
    int success=0; 
    long ldev = 0; 
    long* dev = &ldev; 
    double lTemperature = 0; 
    double* temperature = &lTemperature; 
    success = FLIGetTemperature(ldev, temperature); 
} 

Когда я запускаю свой код, я получаю следующее сообщение об ошибке:

Необработанное исключение типа «System.AccessViolationException» произошло в MyApplication.exe

Дополнительная информация: Попытка чтения или записи в защищенной памяти. Это часто свидетельствует о том, что другая память повреждена.

Я также пробовал маршалинг и IntPtr, но это тоже не работает.

Я пробовал Fliopen, что fucntion работает. Это успех. Ниже приведен код для FliOpen.

[DllImport("/Resources/libfli.dll", EntryPoint = "FLIOpen")] 
    public static extern unsafe int FLIOpen(long* dev, string name, long domain); 

    unsafe public int InitDevice() 
    { 
     long ldev = 0; 
     long* dev = &ldev; 
     int success; 
     string deviceName = "flipro0";// this is default name for device 
     long domainName = 258; //this is default domain name 

     success = FLIOpen(dev, deviceName, domainName); 
     return success; 
    } 

Метод FLIOpen является успехом, хотя

+2

Это не выглядит правильным.Пара вещей, которые нужно попробовать ... Во-первых, у вас есть typelib для DLL, и можете ли вы найти этот метод в oleview? Если это так, пожалуйста, отредактируйте, чтобы опубликовать сообщение о том, что говорит о методе. Во-вторых, я полагаю, вы пытались не использовать указатели на стороне C# и просто использовать 'FLIGetTemperature (long dev, ref double temperature)' как определение 'extern'? – Andrew

+3

Код - это вздор, очень важно, чтобы вы сначала поняли api, прежде чем пытаться его вывести. Вы должны * заставить FLIOpen() работать сначала, чтобы у вас было правильное значение для первого аргумента. –

+0

@ Функция HansPassant my Fliopen работает. У меня есть документация Api, и я редактировал сообщение о том, как они структурируют функцию GetTemperature(). – Neo

ответ

0

Чтение документации, я бы написал что-то вроде этого:

unsafe public void GetTheTemperatureOfTheCamera() 
{ 
    int success=0; 
    long dev = 0; 
    long* ldev = &dev; 
    success = FLIOpen(ldev, deviceName, domainName); //Get the device handle. 

    if (success != 0) 
     throw new Exception("Cannot open device"); 

    double lTemperature = 0; 
    double* temperature = &lTemperature; 
    success = FLIGetTemperature(dev, temperature); 
} 
+0

ldev не указатель, он длинный со значением 0. Посмотрите на мой код выше. – Neo

+0

Мой плохой. Я читал слишком быстро. – tumasgiu

0

Существует несоответствие между C# long параметров и неуправляемого типа flidev_t. Ключевым моментом является то, что long является 64-разрядным типом. Предполагая, что ваш код запущен в Windows, тогда flidev_t, который является псевдонимом C++ long, имеет ширину 32 бит.

Здесь также нет необходимости в небезопасном коде. Вы можете объявить функцию следующим образом:

[DllImport("/Resources/libfli.dll", CallingConvention = CallingConvention.Cdecl)] 
public static extern int FLIGetTemperature(int dev, out double temperature); 

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

Вам нужно будет внести другие изменения в свои другие объявления p/invoke. По сути, всюду вы перевели flidev_t на C# long, вы должны изменить его на int. Или, возможно, даже IntPtr. Тогда вы будете на шаг впереди неуправляемого кода, который в настоящее время не подходит для 64-битного порта, которого я подозреваю!

Начиная с FLIOpen, который собирается быть:

[DllImport("/Resources/libfli.dll", CallingConvention = CallingConvention.Cdecl)] 
public static extern int FLIOpen(out int dev, string name, int domain); 

Ну, параметр домена может быть лучше перевести как C# перечисления с int базового типа.

+0

Я попробую, что прямо сейчас у меня нет камеры. Я попробую, когда я получу камеру от производства. Кроме того, у меня есть еще одна функция для захвата фреймов, которые описаны ниже. [DllImport ("/ Resources/libfli.dll", EntryPoint = "FLIGrabRow")] public static extern unsafe int FLIGrabRow (long dev, void * buff, double width); Защитой метода от производства является следующее. – Neo

+0

// Возьмите ряд изображений. Эта функция захватывает следующую доступную строку изображения с устройства камеры. // Строка ширины ширины помещается в буфер, на который указывает buff. // Размер буфера, на который указывает бафф, должен учитывать битовую глубину изображения, // Значение размера буфера должно быть не менее ширины байтов для 8-битного изображения и не менее 2 * ширины для 16-битное изображение. // Возвращаемое значение: нулевой успех. Без нуля при сбое. // Параметры: dev Камера, чей образ захватить следующую доступную строку. – Neo

+0

// buff Указатель на место размещения следующей доступной строки. Теперь я запутался в пропуске баффа из C#, как бы передать pass, так как это тип void. Если я хочу, чтобы мой размер изображения составлял 2000 x 256, как бы я получил свое объявление в C# – Neo

Смежные вопросы