Как вернуть двойной указатель из C++ DLL на C#?
Я пытаюсь вернуть указатель из моей C++ DLL на C#. Я перепробовал все, но мой указатель типа double не имеет значения.
Ниже мой импорт 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
определение 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.
[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 ответа
Существует несоответствие между вашим 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
базовый тип.
Читая документацию, я написал бы что-то вроде этого:
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);
}