passing pointers when using a DLL

BlitzMax Forums/BlitzMax Programming/passing pointers when using a DLL

Derron(Posted 2012) [#1]
Hi,

a friend asked me to write a filter software for data of a spectrum analyzer. As the raw data has to be processed, I have to connect to a special software via DLL which then would output me the data I then can filter.
The problem are some memory access violations using my code :D.


Some (the ones I need) of the DLL functions are
//pDeviceID = pointer to an integer buffer
XXX_Open(int *pDeviceID, const char *pIni)

XXX_Read_Binary(int DeviceID, const char *pFileName);

//pWavelengthCount = pointer to an integer buffer
XXX_Get_Spectrum_Size(int DeviceID, int Channel, int *pWavelengthCount)

//pWavelengthAxis =  pointer to a buffer array 
//pSpectrum = pointer to an buffer array
XXX_Get_Spectrum_Data(int DeviceID, int Channel, double *pWavelengthAxis, double *pSpectrum)


I converted them (encapsulated in a type):
Type TApp
	Field XXXDLL:Int		= 0
	Field XXXDeviceID:int	= 0
	Field XXXIniFile:string	="filterWin32.ini"
	Field XXX_Open(pDeviceID:Int Ptr, pIni$z) "Win32"
	Field XXX_Read_Binary:int(DeviceID:int, pFileName$z) "Win32"
	Field XXX_Get_Spectrum_Size:int(DeviceID:int, Channel:int, pWavelengthCount:Int Ptr) "Win32"
	Field IrSys_Get_Spectrum_Data:int(DeviceID:int, ChannelSelect:int, pWavelengthAxis:Int Ptr, pSpectrum:Int Ptr) "Win32"


	Method Run:TApp()
		'init interface to XXX
		self.XXXDLL = LoadLibraryA("XXX.dll")
		If Not Self.XXXDLL Then Throw "NO CONNECTION TO XXX"; end

		'init XXX functions
		self.XXX_Open				= GetProcAddress(self.XXXDLL,"XXX_Open")
		'... and the other ones

		'open device - works as expected
		local openRes:int = self.XXX_Open(varptr(self.XXXDeviceID), self.XXXIniFile)

		'read binary - works as expected
		local fileRes:int = self.XXX_Read_Binary(0, "filename.ext" )

'DOES NOT WORK - dataSize keeps 0
		local dataSize:int = 0
		local sizeRes:int = self.XXX_Get_Spectrum_Size(self.XXXDeviceID, 0, varptr(dataSize))
'->> stays 0

'ALSO DOES NOT WORK
		local dataSizeB:TBank = CreateBank(16)
		local sizeResB:int = self.XXX_Get_Spectrum_Size(self.XXXDeviceID, 0, varptr(dataSizeB))
		dataSize = PeekInt(dataSizeB,0)
'->> memory access violation

		if dataSize > 0
			local dbl:double = 0
			local dblSize:int = sizeOf(dbl)
			local dataBankX:TBank	= CreateBank(self.dataSize* dblSize)
			local dataBankY:TBank	= CreateBank(self.dataSize* dblSize)
'DOES NOT WORK TOO
			local dataRes:int		= self.XXX_Get_Spectrum_Data(self.XXXDeviceID, 0, varptr(dataBankX), varptr(dataBankY))
'->> memory access violation

	End Method



The question for me is: how to convert the function calls correctly?

I thought - if the DLL functions need to change values, I have to give them pointers ...
For "XXX_OPEN" it worked perfectly - the external function set the deviceID as it should.
Also the pchar-things seem correct as the Ini-Files were read correctly (else the dll wont work as they need the hardware device).

Like mentioned in the code (the comments) the app keeps crashing when it comes to XXX_Get_Spectrum_XYZ.
Which made me wonder - the param "int *pWavelengthCount" is the same type as "int *pDeviceID" - but only the last one is working.

What to do with the array of doubles ?


Before I forget a detail:
The DLL itself works perfectly - a BCB/c++ sample works as it should.
int WavelengthCount = 0;
  volatile int Result = (*pXXX_Get_Spectrum_Size)(ID,ChannelSelect,&WavelengthCount);

  double *X = new double[WavelengthCount];
  double *Y = new double[WavelengthCount];

  Result = (*pXXX_Get_Spectrum_Data)(ID,ChannelSelect,X,Y);



Hope somebody is able to help.

bye
Ron


edit: forgot to include sizeOf(dblSize) - included in example now

Last edited 2012


JoshK(Posted 2012) [#2]
You are passing a pointer to the bank object. You want to pass a pointer to the bank's data buffer.
self.XXX_Get_Spectrum_Data(self.XXXDeviceID, 0, dataBankX.buf(), dataBankY.buf())



Derron(Posted 2012) [#3]
Ok, will try that tomorrow (as I cannot emulate the device and my usb cable is no 5km long :p).


But what about the part "dataSize" ? It wants to get a pointer to an integer - i gave one but the value keeps staying at "0".

Normally it should return values like "3213" if 3213 samples are stored - which than are needed to give the banks the correct size.


PS: is there another way than banks?
PPS: thanks for the fast answer

bye
Ron

EDIT: hmmpf recognized I used one time "self.dataSize" and the other time the local "dataSize".
And the dataSizeB-variant used the bank - which u said should be used with bank.buf() ...
Think I will do as the manual suggests: bankPointer:Byte Ptr = bank.Lock() and unlock afterwards.
Will examine it tomorrow.

Last edited 2012


JoshK(Posted 2012) [#4]
local dataSize:Int
self.XXX_Get_Spectrum_Size(self.XXXDeviceID, 0, varptr dataSize)


Derron(Posted 2012) [#5]
Thanks Josh
...everything worked (bank.lock() used to get pointer to bank as suggested).

At the end we got data I already mangled out of the binary stream data stored by the machine.
Work done for nothing (except "learning" how to use DLLs from BlitzMax) :(.

bye
Ron


Floyd(Posted 2012) [#6]
At the end we got data I already mangled out of the binary stream data stored by the machine.

Do you mean the data was mangled before it got to your BlitzMax program? If so then I guess you have other problems to solve.

Otherwise there might still be things to try. For example maybe the endianness ( byte order ) is wrong.

Last edited 2012


Derron(Posted 2012) [#7]
the machine stores its data in a different format than used to me (12bit numbers) and some kind of interchaining. Analog to Digital conversion is needed - and this is the thing the DLL seems to do for me. But as a kind of dongle they needed the hardware (the machine) to be present to work.

Think "mangle" was not the best word to use..... I had to do some joyless work to get the data I wanted.


bye
Ron