11-20-2014 04:14 AM
I have an old MFC based software that is compiled in Microsoft Visual C++ 6.0. I'm using a LabVIEW compiled .dll in this program to control the Acquisition and get my datapoints. But when I close this application (in a normal way) the following error message appears: "LABVIEW.lib was not called from a LabVIEW process." What could be the cause here?
I am using some functions directly from the lvrt.dll, maybe this can help us solve the problem. (I didn't include the header file code etc...)
dllHandleLVRT = LoadLibrary("lvrt.dll");
if(!dllHandleLVRT)
{
iStatus = MS_VI_NO_LVRT;
m_cAxeData[0].m_pLog->LogMsg("Loadlibrary"," Couldn't load Labview Run time: LVRT.dll",0);
AfxMessageBox(" Couldn't load Labview Run time: LVRT.dll", MB_OK);
return;
}
hdlDSNewHandle = (paramDSNewHandle) GetProcAddress(dllHandleLVRT, "DSNewHandle");
hdlDSDisposeHandle = (paramDSDisposeHandle) GetProcAddress(dllHandleLVRT, "DSDisposeHandle");
Can anyone help me solve this message box at the end of my program?
Thanks already!
Filip.
11-24-2014 05:49 AM
Hi I am an Application Engineer from National Instruments. After some researching I want to clarify some things:
1. Do you know what version of LabVIEW was used to create the .dll and what version are you using now to access it?
2. As I understand LabVIEW is only involved as the .dll and in no other way?
3. Was it working properly before? If not, this link might be of use to confirm if everything is set up right:
http://www.ni.com/white-paper/3189/en/
Possible reasons could be that your .dll uses some functions from an older version of LabVIEW which are not available in a newer version installed on your PC, but I am not sure if that is the problem.
11-24-2014 08:35 AM
Hi Marius,
Thanks already for your suggestions!
Here are my answers:
1. It's all on the same runtime. I compile my .dll with LabVIEW 2012 and I package it all in an installer including the runtime that comes with LV2012. I access the .dll from my Visual C++ 6.0 MFC code.
2. Yes. I call the .dll from Visual C++. There is no other program (LabVIEW or other) using this .dll (at least not that I know of 😉 ).
3. This is a more difficult question. The structures that I need in my .dll are vastly more complicated than the examples in the white paper that you suggested. This makes it difficult to assess if I'm declaring and using everything the right way.
Btw. I made a mistake in the description of my forum post. It's actually LABVIEWV.lib (there's an extra V in there)
Here's where I think the problem may be,...
:
hdlLVMS3Shaft = (LVMS3ShaftHandle)hdlDSNewHandle(sizeof(LVMS3Shaft));
// ptrLVMS3Shaft = (LVMS3Shaft*)calloc(1, sizeof(LVMS3Shaft));
memset(*hdlLVMS3Shaft,0,sizeof(LVMS3Shaft));
(*hdlLVMS3Shaft)->PhaseReferenceChannels = hdlAllocatePhaseReferenceChannelArray(4);
memset(*((*hdlLVMS3Shaft)->PhaseReferenceChannels),0,sizeof(PhaseReferenceChannelArrayBase)+4);
(*hdlLVMS3Shaft)->Channels = hdlAllocateCRIOChannelArray(MAX_SENSOR);
memset(*((*hdlLVMS3Shaft)->Channels),0,sizeof(CRIOChannelArrayBase) + MAX_SENSOR);
(*hdlLVMS3Shaft)->IPAddress = (LStrHandle)hdlDSNewHandle(sizeof(LStr)+15);
memset(*((*hdlLVMS3Shaft)->IPAddress),0,sizeof(LStr)+15);
(*hdlLVMS3Shaft)->user = (LStrHandle)hdlDSNewHandle(sizeof(LStr)+255);
memset(*((*hdlLVMS3Shaft)->user),0,sizeof(LStr)+255);
(*hdlLVMS3Shaft)->password = (LStrHandle)hdlDSNewHandle(sizeof(LStr)+255);
memset(*((*hdlLVMS3Shaft)->password),0,sizeof(LStr)+255);
hdlCRIOSingleRotationData = (CRIOSingleRotationDataHandle)hdlDSNewHandle(sizeof(CRIOSingleRotationData));
memset(*hdlCRIOSingleRotationData, 0, sizeof(CRIOSingleRotationData));
And the header file of the .dll
#ifndef LVMS3CRIO_h #define LVMS3CRIO_h #include "extcode.h" #pragma pack(push) #pragma pack(1) #ifdef __cplusplus extern "C" { #endif typedef uint16_t SamplingMode; #define SamplingMode_Synchronous 0 #define SamplingMode_Asynchronous 1 typedef struct { int32_t dimSizes[2]; double Numeric[1]; } DoubleArrayBase; typedef DoubleArrayBase **DoubleArray; typedef struct { int32_t dimSize; double Numeric[1]; } DoubleArray1Base; typedef DoubleArray1Base **DoubleArray1; typedef struct { int64_t StartTimeStampInTicks; double RPM; SamplingMode SamplingMode; DoubleArray SamplesInVolts; uint8_t PhaseReferenceUsed; DoubleArray1 InterPhaseReferenceAnglesInRad; } CRIOSingleRotationData; typedef uint16_t ShaftType; #define ShaftType_Primary 0 #define ShaftType_Secondary 1 #define ShaftType_Auxiliary 2 typedef struct { int32_t VIBCRIOChannelNbr; double VIBScalingFactor; double VIBOffsetVoltage; } CRIOChannel; typedef struct { int32_t dimSize; CRIOChannel Channel[1]; } CRIOChannelArrayBase; typedef CRIOChannelArrayBase **CRIOChannelArray; typedef struct { int32_t PHCRIOChannelNmbr; double BlankingInSec; double ThresholdInVolts; double FilterSettleTimeInSec; double PHScalingFactor; double PHOffsetVoltage; } PhaseReferenceChannel; typedef struct { int32_t dimSize; PhaseReferenceChannel PhaseReferenceChannel[1]; } PhaseReferenceChannelArrayBase; typedef PhaseReferenceChannelArrayBase **PhaseReferenceChannelArray; typedef uint16_t SamplingMode1; #define SamplingMode1_Synchronous 0 #define SamplingMode1_Asynchronous 1 typedef struct { ShaftType ShaftType; int32_t SamplesPerRotation; double RegimeSlowMinimumRPM; double NominalRPM; LStrHandle IPAddress; CRIOChannelArray Channels; PhaseReferenceChannelArray PhaseReferenceChannels; SamplingMode1 SamplingMode; LStrHandle user; LStrHandle password; } LVMS3Shaft; /*! * This VI loads that LVMS Acquisition process. The LVMS Acquisition process * will save its log files in the <b>logFilePath</b> directory. */ int32_t __stdcall Load(Path *logFilePath); /*! * Stop */ int32_t __stdcall Stop(void); /*! * GetNmbQueuedRotations */ int32_t __stdcall GetNmbQueuedRotations(char CRIO[], int32_t *nmbQueuedRotations); /*! * This VI stops the LVMS Acquisition process. */ int32_t __stdcall UnLoad(void); /*! * GetRotationBlock */ int32_t __stdcall GetRotationBlock(char IPAddressCRIO[], int32_t nbOfRotations, uint32_t maxTimeoutInms, CRIOSingleRotationData *CRIOSingleRotationData); /*! * GetSingleRotation */ int32_t __stdcall GetSingleRotation(char IPAddressCRIO[], CRIOSingleRotationData *CRIOSingleRotationData); /*! * LVMS3Configure */ int32_t __stdcall LVMS3Configure(LVMS3Shaft *LVMS3Shaft); /*! * LVMS3Start */ int32_t __stdcall LVMS3Start(LVMS3Shaft *LVMS3Shaft); /*! * LVMS3String2Path */ void __stdcall LVMS3String2Path(char inputPathStr[], Path *outPath); /*! * WriteRelayState */ int32_t __stdcall WriteRelayState(char IPAddressCRIO[], uint8_t relayNumber, LVBoolean relayState); /*! * ResetConnectionCounter */ void __stdcall ResetConnectionCounter(LVMS3Shaft *LVMS3Shaft); /*! * RemoveOneFromConnectionCounter */ void __stdcall RemoveOneFromConnectionCounter(LVMS3Shaft *LVMS3Shaft); /*! * IsLastConnectionCounter */ void __stdcall IsLastConnectionCounter(LVMS3Shaft *LVMS3Shaft, LVBoolean *isLast); /*! * AddOneToConnectionCounter */ void __stdcall AddOneToConnectionCounter(LVMS3Shaft *LVMS3Shaft); /*! * LVMS3WriteAllRelayStates */ int32_t __stdcall LVMS3WriteAllRelayStates(char IPAddressCRIO[], uint8_t relayState); long __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module); /* * Memory Allocation/Resize/Deallocation APIs for type 'DoubleArray' */ DoubleArray __cdecl AllocateDoubleArray (int32 *dimSizeArr); MgErr __cdecl ResizeDoubleArray (DoubleArray *hdlPtr, int32 *dimSizeArr); MgErr __cdecl DeAllocateDoubleArray (DoubleArray *hdlPtr); /* * Memory Allocation/Resize/Deallocation APIs for type 'DoubleArray1' */ DoubleArray1 __cdecl AllocateDoubleArray1 (int32 elmtCount); MgErr __cdecl ResizeDoubleArray1 (DoubleArray1 *hdlPtr, int32 elmtCount); MgErr __cdecl DeAllocateDoubleArray1 (DoubleArray1 *hdlPtr); /* * Memory Allocation/Resize/Deallocation APIs for type 'CRIOChannelArray' */ CRIOChannelArray __cdecl AllocateCRIOChannelArray (int32 elmtCount); MgErr __cdecl ResizeCRIOChannelArray (CRIOChannelArray *hdlPtr, int32 elmtCount); MgErr __cdecl DeAllocateCRIOChannelArray (CRIOChannelArray *hdlPtr); /* * Memory Allocation/Resize/Deallocation APIs for type 'PhaseReferenceChannelArray' */ PhaseReferenceChannelArray __cdecl AllocatePhaseReferenceChannelArray (int32 elmtCount); MgErr __cdecl ResizePhaseReferenceChannelArray (PhaseReferenceChannelArray *hdlPtr, int32 elmtCount); MgErr __cdecl DeAllocatePhaseReferenceChannelArray (PhaseReferenceChannelArray *hdlPtr); #ifdef __cplusplus } // extern "C" #endif #pragma pack(pop) #endif //LVMS3CRIO_h
11-24-2014 11:23 AM
Thank you for answering my questions. At this point I think it would be a good idea to checked whether the problem is definetly in the way you are calling the .dll .
Could you please try and compile a fairly simple .dll as described in the white paper and try calling it in the same way as you are calling this .dll? If you are able to call the .dll sucessfully the problem is most likely in the .dll itself, which is what I suspect.
Kind Regards,
12-04-2014 01:34 AM
I was unable to recreate the problem using less complex structures and code. I do have to note that the current code calls the loadlibrary function loading the my labview dll and and the lvrt.dll several times from different threads and it calls the freelibrary function the same way. I also noticed that if I leave out the freelibrary function, the problem does dissappear. But instead I introduce a memory leak.
Any thoughts?
Regards,
Filip.