12-18-2009 10:13 AM
Hello,
So I have been trying and trying to get two different parts of my project working together, and right now this involves calling a LabVIEW analysis function (namely, PeakD) in a C/C++ executable. I have made sure to include all necessary header files from the resource folder and define all relevant structs, in addition to reading about the TD1/TD2 data types and the prototype header but I still cannot figure out what I am doing wrong! Here is the code I have written:
// PeakD.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <stdio.h> #include <windows.h> #include "extcode.h"/* Typedefs */typedef struct { long dimSize; double elt[1];} TD2;typedef TD2 **TD2Hdl;typedef struct { TD2Hdl Input_Array; double Threshold; long Width; unsigned long PeaksValleys; TD2Hdl Peak_Locations; TD2Hdl Peak_Amplitudes; TD2Hdl Peak_Second_Derivatives; long elt8; long elt9;} TD1;typedef struct { long Span; long Index; long NHistoryPts; long Len; long PrevSign; long unused; unsigned long RinvQtPointer; unsigned long FitBufferPointer; unsigned long HistoryPointer; unsigned long PrevCoeffPointer; unsigned long DataPointer; unsigned long slackForRinvQt; unsigned long slackForFitBuffer; unsigned long slackForHistory; unsigned long slackForPrevCoeff; unsigned long slackForData;} TD3;/* Prototypes */typedef void (*MYPROC)(TD1 *PeakApp, TD3 *pPEAKINT, TD2Hdl *SavedData, long *pErr);void _tmain(int argc, _TCHAR* argv[]){ // File: RUNTIME.C // Sample code that uses LoadLibrary and GetProcAddress to access myFunction from MYDLL.DLL. // You will need to include stdio.h and windows.h in your project to use this code HINSTANCE hinstLib; MYPROC ProcAdd; BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; // Get a handle to the DLL module. hinstLib = LoadLibrary(_T("lvanlys")); // Function inputs. TD1 *PeakApp = 0; TD3 *pPEAKINT = 0; TD2Hdl *SavedData = 0; long *pErr = 0; PeakApp = new TD1; pPEAKINT = new TD3; SavedData = new TD2Hdl; pErr = new long; PeakApp->Input_Array[0]->dimSize = 1; PeakApp->Input_Array[0]->elt[0] = 1; PeakApp->Threshold = 10; // Between 0 and 60 PeakApp->Width = 10; // 0 is Peaks, 1 is Valleys PeakApp->PeaksValleys = 0; // Process the beginning of data PeakApp->elt8 = 1; // Process the end of data PeakApp->elt9 = 1; // If the handle is valid, try to get the function address. if (hinstLib != NULL) { ProcAdd = (MYPROC) GetProcAddress(hinstLib, "PeakD"); // If the function address is valid, call the function. if (fRunTimeLinkSuccess = (ProcAdd != NULL)) //(ProcAdd) ("message via DLL function\n"); (ProcAdd) (PeakApp, pPEAKINT, SavedData, pErr); // Free the DLL module fFreeResult = FreeLibrary(hinstLib); } // If unable to call the DLL function, use an alternative if (! fRunTimeLinkSuccess) printf("message via alternative method\n"); }
I am supposed to pass pointers (or more specifically, handles) to the "NI Data Objects" which have a long which signifies the size (dim_size) and the rest of the elements (in elt[]). LabVIEW 8 shows this function's prototype and the necessary pointers as being:
typedef long (*MYPROC)(void *PeakApp, void *pPEAKINT, Array1DDouble ***SavedData, long *pErr);
Does this mean that I have to manually cast my integer-based pointer into a (void*) when entering MYPROC (PeakD)? This hasn't worked for me so far, so I'm assuming that the problem lies with my data structures. Anyways, I would greatly appreciate your help on this matter, thanks.
~Ali
Solved! Go to Solution.
12-18-2009 10:16 AM
12-21-2009 11:55 AM
Hi OfMagnitude,
I am a little confused with your application. Where is the PeakD integer?
thanks
FLash
12-21-2009 12:24 PM
Thanks for your reply Flash. PeakD() is actually a function, let me copy and paste the exact NI Data types from LabView 8's "Call Library Function" window:
long PeakD(Array1DDouble **y, Array1DDouble **x, Array1DDouble **weight, Array1DDouble **lambda, double p, double *merit);
I was originally calling the version from LabVIEW 7's lvanlys.dll (which explains why I had a different number of arguments). But basically, Array1DDouble is a handle to the array's data, which I've read that includes a long (for element size) and then the actual data (which is stored in an array). Can someone please confirm this with me, and help me to link to this function?
12-22-2009 11:53 AM
Looks like your "prototype" only applies WITHIN LabVIEW/CVI ITSELF, i.e., your documentation neglects to account for actual C data structs (or clusters as you call them). Care to explain this to me?
12-22-2009 02:27 PM
I have declared all of my structs properly, and I am allocating my handles on the heap using DSNewHandle instead of malloc:
// use DSNewHandle instead of malloc to allocate memory
handle_var = (TD1**)DSNewHandle(sizeof(TD1));
Is there any solid reference material for these TD1/TD2/TD3 structures, for the plethora of LabVIEW analysis functions that are available?
12-22-2009 04:42 PM
Hi OfMagnitude,
I am not completely sure that these functions are open to the public. I will have to get back to you.
FLash
12-23-2009 01:17 PM
Hi OfMagnitude,
I confirmed with our R&D that using this DLL as a standalone outside of LabVIEW is not supported. You are free to work on it yourself but we cannot provide support on it. Sorry.
FLash
12-23-2009 02:36 PM
12-23-2009 02:55 PM
The PeakD function is called by Peak Detector.vi and there is a description of the algorithm in that function's help.
Since you must have LabVIEW in order to have the lvanlys.dll, it would be pretty simple to make a dll from the LabVIEW VI itself.