Problem with Void Pointer Casting

Hey!

I have been recently working on a software in VC++ that can communicate with a decive (Oscilloscope). The manufacturer provided with Library (.h file and a lib x64) based on C.
The problem is that some of the functions in the DLL have viod pointers. here are a few examples.

1
2
3
4
5
6
7
8
9
#include "CAENDIGITIZER.h"

/**************************************************************************//**
* \param 	[IN] waveforms      
* \param 	[IN] events      
******************************************************************************/
CAEN_DGTZ_ErrorCode CAENDGTZ_API CAEN_DGTZ_MallocDPPWaveforms(int handle, void **waveforms, uint32_t *allocatedSize);

CAEN_DGTZ_ErrorCode CAENDGTZ_API CAEN_DGTZ_MallocDPPEvents(int handle, void **events, uint32_t *allocatedSize);


The input parameters are not void, but are type template of:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
typedef struct // for void **events
{
        uint32_t Format;
        uint32_t TimeTag;
	int16_t ChargeShort;	
	int16_t ChargeLong;
        int16_t Baseline;
	int16_t Pur;
    uint32_t *Waveforms; 
} CAEN_DGTZ_DPP_PSD_Event_t;

typedef struct		//for void **Waveforms
{
    uint32_t Ns;    
    uint8_t  dualTrace;    
    uint8_t  anlgProbe;    
    uint8_t  dgtProbe1;
    uint8_t  dgtProbe2;
    uint16_t *Trace1;
    uint16_t *Trace2;
    uint8_t  *DTrace1;
    uint8_t  *DTrace2;
    uint8_t  *DTrace3;
    uint8_t  *DTrace4;
} CAEN_DGTZ_DPP_PSD_Waveforms_t;


In C, i can easily call the function with a script that reads more or less like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// main.c
CAEN_DGTZ_DPP_PSD_Event_t       *Events1[MaxNChannels];  // events buffer
CAEN_DGTZ_DPP_PSD_Waveforms_t   *Waveform=NULL;         // waveforms buffer
int AllocatedSize, handle;

public: void progDEVICE()
	    /* Allocate memory for the events */
    ret = CAEN_DGTZ_MallocDPPEvents(handle, Events1, &AllocatedSize); 
    /* Allocate memory for the waveforms */
    ret = CAEN_DGTZ_MallocDPPWaveforms(handle, &Waveform, &AllocatedSize); 
    if (!ret==0) {
        printf("Can't allocate memory buffers\n"); 
    }
}


Due to extremely huge ammount of data processing in realtime and other preferences, I am inclined to use C++. However, the bugger is that C++ donot like void pointers without having an explicit casting. but i am unable to cast these for the life of me:(
I am using VC++2010 Pro. MScompiler and intel Compiler only turn up with nasty casting errors.

error C2664: 'CAEN_DGTZ_MallocDPPEvents' : cannot convert parameter 2 from 'CAEN_DGTZ_DPP_PSD_Event_t *[8]' to 'void **'	


I was hoping someone can help me out. I donot have the source code of the library, but only the .h and .lib files.

Thanks a Lot!
cheers
Last edited on
It's not clear what CAEN_DGTZ_MallocDPPEvents is expecting, so I don't know if it's expecting an array of CAEN_DGTZ_DPP_PSD_Event_t*. You don't pass in the number of elements in that array, so I don't think it's expecting an array.

Do you have anything that describes the parameters of CAEN_DGTZ_MallocDPPEvents()?

EDIT:
You have to be extremely careful when dealing with void*. It means you're bypassing the language's type system and you're taking full responsibility for ensuring the right thing is done.

Thinking about it further, it has to allocate space for just one Event at a time, so the code should probably look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool progDEVICE()
{
	// Allocate memory for the waveforms
	int ret = CAEN_DGTZ_MallocDPPWaveforms(handle, &Waveform, &AllocatedSize); 
	if (ret)
		return false;

	// Allocate memory for the events
	for (size_t i = 0; i < MaxNChannels; ++i)
	{
		int ret = CAEN_DGTZ_MallocDPPEvents(handle, &Events1[i], &AllocatedSize);
		if (ret)
		{
			// Out of memory, release what we have so far
			CAEN_DGTZ_FreeDPPWaveforms(handle, &Waveform); // dunno if this exists
			for (size_t j = 0; j < i; ++j)
				CAEN_DGTZ_FreeDPPEvents(handle &Events[j]); // dunno if this exists
			return false;
		}
	}

	return true;
}
Last edited on
Thank you for the inpu.

the second parameter of CAEN_DGTZ_MallocDPPEvents (void **events) is expecting CAEN_DGTZ_DPP_PSD_Event_t. for CAEN_DGTZ_MallocDPPWaveforms(void **waveforms) is expecting CAEN_DGTZ_DPP_PSD_Waveforms_t.

i m currently using reinterpret_cast<void**>(&Waveform) & reinterpret_cast<void**>(Events1). The compilation now proceeds without a glitch, and the device is happy with my call(no errors thrown to ret), but it is is not configured properly.

MallocDPPEvents (& MallocDPPwaveforms) basically Allocates the event (or waveform) buffer matrix which is handled by the GetDPPEvents function. The matrix has one event array per channel and must be declared as a MAX_CH-sized array of pointers.

two events to free memory that you mentioned do exist, but the program will not compile without recasting, and reinterpret_cast is proving useless :(
The library is certainly making poor use of typing.

I would have expected CAEN_DGTZ_MallocDPPWaveforms to have passed CAEN_DGTZ_DPP_PSD_Waveforms_t ** rather than void **.

Also, the Waveforms member of the CAEN_DGTZ_DPP_PSD_Event_t struct is declared as uint32_t *Waveforms;
This states that Waveforms is a pointer to an int32_t. While that could be true, it seems more likely that it it really a pointer to CAEN_DGTZ_DPP_PSD_Waveforms_t and should have been declared as CAEN_DGTZ_DPP_PSD_Waveforms_t *. Hopefully, the library is using that a "generic" pointer type (and recasting it internally) and not storing the adddress of the waveform information in the int32 pointed at as that would case a problem since pointers in your environment are 64 bits.

When you say you're using reinterpret_cast, I'm assuming something like this?
1
2
3
void * vp_events[MAX_CH];
CAEN_DGTZ_MallocDPPEvents(handle,vp_ events, &AllocatedSize);
events1 = reinterpret_cast<CAEN_DGTZ_DPP_PSD_Event_t **> vp_events;

When you say the "device is not configured correctly", can you give more specifics?

You should certainly be able to pass vp_events back to the corresponding free routine without recasting, assuming it's expecting void ** also.

BTW, the description of those params is incorrect.
1
2
param 	[IN] waveforms      
param 	[IN] events      

Those should be described as [OUT], since the results of the malloc calls are stored in the supplied pointers.

edit: I've found C++ compilers forgiving of passing typed pointers to a function that takes a void * (as expected), but they don't seem to like typed pointers to pointers as in your situation. Perhaps someone more knowledgable might have an explanation.



Last edited on
i tried two forms of casting:

1
2
3
4
5
6
7
8
9
10
11
12
13
// main.c
CAEN_DGTZ_DPP_PSD_Event_t       *Events1[MaxNChannels];  // events buffer
CAEN_DGTZ_DPP_PSD_Waveforms_t   *Waveform=NULL;         // waveforms buffer
int AllocatedSize, handle;

public: void progDEVICE()
//1st form
	ret = CAEN_DGTZ_MallocDPPEvents(handleVX1720, (void** )Events1, &AllocatedSize);	/* memory for the events */
	if (!ret == 0) {lblERROR->Text = L"Error in EVENTmem: " + whatERROR(ret);cnt++;}
//2nd form
         ret = CAEN_DGTZ_MallocDPPEvents(handleVX1720, reinterpret_cast<void**>Events1, &AllocatedSize);	/* memory for the events */
    }
}


this is, you first pass on the parameters, and then using the above codes, configure the device memory and give me the results (i realized they are incorrect too do define waveforms and events as [IN]), so that you can read the data (with other GetData function) . Once I call these function, I get no transfer of data into my buffer pointer from the device.

Using the same codes in C, which is written with the same call structure, I get read outs.

I actually tried refining the call function from
1
2
3
CAEN_DGTZ_ErrorCode CAENDGTZ_API CAEN_DGTZ_MallocDPPWaveforms(int handle, void **waveforms, uint32_t *allocatedSize);
//to
CAEN_DGTZ_ErrorCode CAENDGTZ_API CAEN_DGTZ_MallocDPPWaveforms(int handle, CAEN_DGTZ_DPP_PSD_Waveforms_t **waveforms, uint32_t *allocatedSize);


compiler is happy and no error reported by the return of the function, but not my read out. :( But I think suggests that the library is not recasting the void to int internally..
btw, is it safe to change void** to CAEN_DGTZ_DPP_PSD_Waveforms_t ** in the function declaration? im not sure.
Last edited on
Topic archived. No new replies allowed.