LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Global variables declared inside DLL

Hello,

 

is it safe to declare a Global variable inside DLL and use it somewhere further in other DLL (same proccess, due to LabView not sure about thread...)?

 

I need to pass a LVUserEvent pointer to a callback function, but the callback registering function, and even the callback prototype itself

do not take any user parameters...

 

In the C example that ships with the api I work with, the callback function works with a global queue to pass data further.

 

 

I was thinking about doing this :

 

//declare a Global variables (pointers) in the DLL, I do not know where to declare this yet...

 

LVUserEventRef *gPmsg = NULL; //The LVUserEvent pointer, I let LabView create the UserEvent.

 

UserData *gPdata; //data structure global pointer, I let LabView allocate the struct and use this only to supply the pointer at it

 

//----Functions I will export-----

 

//Call back function that is called

 

void onDataAvailable(struct XsCallbackPlainC* cb, struct XsDevice* dev, const struct XsDataPacket* packet) //Just prototype from sdk
{    
    gPdata->Data = getDataFromPacket(packet); //Pass the data to a LabView operable memory

    PostLVUserEvent(*gPmsg, (void*)gPdata); //So I get the gPdata in the event structure, I am not sure if this is possible
}

 

//The callback registration itself, this piece of code should give the Global pointer proper values a register the callback

//LVData is allocated in LabView through standard cluster constant on block diagram

void RegisterCallBack(LVUserEventRef *LVmsg, UserData *LVData)


{

    gPmsg = LVmsg; //LVmsg is created in LabView through standard Create User Event function, so here I would just point the pointer to it.

    gPdata = LVData; //same as above but for data.

    callbackHandler.m_onDataAvailable = onDataAvailable; //Pointer to the callback function above

    XsDevice_addCallbackHandler(foundDevice, &callbackHandler, TRUE);

}

 

Please help me, as I am getting only segfaults and no events.

I didnt find anywhere if this is possible in LabView.

 

Regards

 

 

0 Kudos
Message 1 of 6
(4,078 Views)

I've never written a DLL that uses PostLVUserEvent, so I could be completely wrong here. However, my guess is the problem is that you're trying to let LabVIEW allocate memory for the data structure. LabVIEW has no way to know that you need to keep the structure at that memory location after the DLL call to register the callback completes; it's quite possible it's moving that structure somewhere else or freeing it (if it's not used elsewhere in your LabVIEW code), which could cause a segfault when you then try to write to that address. You need to allocate that memory either in the DLL or using DSNewPtr in your LabVIEW code so you can guarantee that that memory will stay reserved for use by your callback. Then you can use MoveBlock or GetValueByPointer to get that data into LabVIEW.

0 Kudos
Message 2 of 6
(4,050 Views)

Good,

 

I figured another way out. I will not pass the data directly in the callback function, but I will only pass a single pointer to the datapacket I recieved.

 

Pleas give me an advice, what kind of data type should I use when creating the LVUserEvent in LabView.

I thought of standard integer...

 

it looks like this now:

 

void onDataAvailable(struct XsCallbackPlainC* cb, struct XsDevice* dev, const struct XsDataPacket* packet)
{
    MgErr ret = -1;
    if(packet != NULL)
    {
        XsDataPacket *copyOfPacket = (XsDataPacket*)malloc(sizeof *copyOfPacket); //Allocate packet copy
        XsDataPacket_copy(packet, copyOfPacket); //Copy the packet content to a memory that is under my command
        ret = PostLVUserEvent(*gPmsg, (void*)copyOfPacket); //send the pointer to the new packet to the event struct
    }
}

 

Once I get the packet I am trying to do something like this inside the (or after) event :

 

void DequeuePacket(PPacket *pPacket, G700Data *Data)
{
    XsDataPacket *packet;
    packet = (XsDataPacket*)pPacket;

    if(XsDataPacket_containsOrientation(packet))
    {
        XsEuler euler;
        XsDataPacket_orientationEuler(packet, &euler, XDI_CoordSysEnu);
        Data->Pitch = euler.m_pitch;
        Data->Roll = euler.m_roll;
        Data->Yaw = euler.m_yaw;
    }
    else Data->Orient = 0;

    if(XsDataPacket_containsLatitudeLongitude(packet))
    {
        XsVector GPS;
        XsVector_construct(&GPS, 2, NULL);
        XsDataPacket_latitudeLongitude(packet, &GPS);
        Data->Lat = GPS.m_data[0];
        Data->Lon = GPS.m_data[1];
        Data->Position = 1;
        XsVector_destruct(&GPS);
    }
    else Data->Position = 0;
    
    if(XsDataPacket_containsAltitude(packet))
    {
        Data->Alt = XsDataPacket_altitude(packet);
        Data->Altitude = 1;
    }
    else Data->Altitude = 0;
    
    if(XsDataPacket_containsVelocity(packet))
    {
        XsVector speed;
        XsVector_construct(&speed, 3, NULL);
        XsDataPacket_velocity(packet, &speed, XDI_CoordSysNwu);
        Data->SpeedN = speed.m_data[0];
        Data->SpeedW = speed.m_data[1];
        Data->SpeedU = speed.m_data[2];
        Data->Speed = 1;
        XsVector_destruct(&speed);
    }
    else Data->Speed = 0;

    if(XsDataPacket_containsCalibratedAcceleration(packet))
    {
        XsVector Acc;
        XsVector_construct(&Acc, 3, NULL);
        XsDataPacket_calibratedAcceleration(packet, &Acc);
        Data->accX = Acc.m_data[0];
        Data->accY = Acc.m_data[1];
        Data->accZ = Acc.m_data[2];
        Data->Accel = 1;
        XsVector_destruct(&Acc);
    }
    else Data->Accel = 0;

    XsDataPacket_destruct(packet); //Free the packet from the queue
}

 

Here I decode the data a free the memory used by the copy of the packet.

The decoded data goes into a LabView struct, that is passed in (as pointer in parameters), so no segfaults I hope...

 

Thanks for advice, I hope I can somehow get this working...

0 Kudos
Message 3 of 6
(4,046 Views)

So...

 

I figured out what is the problem. It seems, that the API constructors for the structures do not allocate the struct properly or in a weaird way.

I cannot take a look at those functions, becouse those are hidden in DLLs, but once the code jumps out of the function, where it was used, the struct dies. I was like 100% sure if I call a constructor from the API, it would properly allocate the structure, but...

 

Those structures in that API are very complex packing several more structures with arrays etc, so reinventing proper allocations for each of these is over my head...

0 Kudos
Message 4 of 6
(4,023 Views)

I need a bit more help here.

 

I successfuly made my app work, everything works without errors.

After I stop the app, I get no errors. I can access the HW the app used without problems from other app.

 

When I close the VI, once it unloads the DLL, it crashes with access violation.

This happens only, if I "touch" the USB driver functions. If LabView just loads the DLL and unloads, no crash...

 

This is the debugger output visual studio generates for .exe file:

 

'MTi-G700.exe': Unloaded 'D:\WORK\C++\Projects\Xsens XDA wrapper\XDA_wrapper\Debug\XDA_wrapper.dll'
'MTi-G700.exe': Unloaded 'C:\Windows\System32\msvcr100d.dll'
'MTi-G700.exe': Unloaded 'D:\WORK\C++\Projects\Xsens XDA wrapper\XDA_wrapper\Debug\xsensdeviceapi32.dll'
First-chance exception at 0x51b4622e in MTi-G700.exe: 0xC0000005: Access violation reading location 0x51b4622e.
Unhandled exception at 0x51b4622e in MTi-G700.exe: 0xC0000005: Access violation reading location 0x51b4622e.
The program '[5848] MTi-G700.exe: Native' has exited with code -1073741819 (0xc0000005).

 

Please help me, guide me, what might be the cause of this...

 

So far, the solution I had was to disable the error reporting...

 

Error.png

0 Kudos
Message 5 of 6
(4,009 Views)

So,

 

this was caused, by corrupted heap. It woked fine in debug config, once in release, it crashed.

I had some wrong memory management in the dll code.

0 Kudos
Message 6 of 6
(3,957 Views)