LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

"undefined symbol" error while using a custom instrument driver

Luis and Markus: Don't know which was the reason, but definitely when adding the library source file (NOT the instrument!) to the project it compiled and linked ok. I had both the SDK lib and the dll import library included in the project, but that didn't prevented the undefined symbol error to appear when using the instrument.

 

 

In the meanwhile I have successfully compiled the "proprietary" part of the library, created the .fp and included in a test project to test, finding another problem. In the library there is a function that is intended to be installed directly as a control callback in the UIR editor: when the program runs I receive the "not a known function" error when loading the panel.

I seem to have understood that the problem lies in CVICALLBACK macro preceding the function, while all other library function macro (and fp creation prefix) is CVIFUNC. Based on this hypothesis, I changed the function prefix to CVIFUNC_C, which maps to CVICDECL the same as CVICALLBACK: the library now compiles and links without errors and the program runs as expected. Is my assumption correct? Do I have to expect troubles on this item?

 

 

 

And finally a perverse question: how do NI succeeded in integrating WinSDK functions in the Programmer's Toolbox without need to add anything to the projects but the single toolbox header file?

Message Edited by Roberto Bozzolo on 05-20-2010 04:20 PM


Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 11 of 16
(1,683 Views)

Markus,

 

The problem I was having with that scenario is that I was imagining that Roberto had been able to link his project, that contained his instrument source, without including the additional libraries in his project. But looking at Roberto's latest reply, it now looks as if I misunderstood this. He's saying that he did add those libraries to the project. Well, if that's the case, then I'd expect the link to be successful whether the instrument was added as source or as a binary object. So I'm still confused on this point.

 

Roberto,

 

The answer to the perverse question is that CVI automatically links in a handful of core SDK libraries, so that programmers don't need to explicitly add them to their CVI project. I'm pretty sure, then, that toolbox does not use any SDK functionality outside of those libraries. This is the set of libraries we link to by default: kernel32.lib, gdi32.lib, user32.lib, advapi32.lib, uuid.lib and winmm.lib. You can see this list in the Programmer Reference>>Compiler/Linker Issues>>Calling Interface to Win32 API Functions in LabWindows/CVI>>Automatic Loading of Interface to the Win32 API Import Libraries help topic of the CVI help.

 

Luis

0 Kudos
Message 12 of 16
(1,667 Views)

Hi Luis,

I am still in trouble with that callback function in the instrument. I have narrowed down the situation to a little test program and related sample fp file that I am attaching to this post: can you look at it? In my machine if I  exclude the InstallCtrlcallback function I receive a "not a known function" error referred to the callback function included in the fp library. Can you explain me why?

 

Referring to one of your preceding posts, I'd have no problem in including some libraries in my projects, but unfortunately this does not remove the undefined symbol error, as you can see in sample 2, where a different .fp includes a call to a SDK function. See test2 project which includes the new instrument.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
Download All
0 Kudos
Message 13 of 16
(1,655 Views)

Okay, let's take these one at a time.

 

The callback function issue, actually, has nothing to do with what I was talking about earlier in the thread. This runtime error that you're getting happens inside the LoadPanel function when the CVI Run-Time Engine cannot find, in your program, the implementation for some callback function that is specified in the .uir. To understand why this particular function is missing from your program, you have to understand a bit about how the linker works: a static library, or an import library, or even the program file of an instrument driver, are only linked into the final EXE or DLL if something else in your project references it -- and unfortunately, a simple name inside a .uir file does not count as a reference, since the linker knows nothing of a .uir or its contents. It has to be an actual C code reference. Therefore, when you excluded the InstallCtrlCallback function call, you also removed the only reference to any function in your driver, and so the CVI linker left out your driver altogether.

 

So why does the problem go away when you add the source file to the project? That's because any file that's physically in the project is always linked in, even if nothing else references it (for historical reasons, to support LoadExternalModule, etc...). The problem here is that when you had the .fp in the project, CVI doesn't follow this same rule for the program file of the .fp. It  just assumes that you don't really need the .fp, and so leaves it out.

 

So what can you do about this? Well, one fix would be to go to the Build>>External Compiler Support dialog, create a callback table for your .uir, and then add this file to your project. The problem with this solution is that it pushes the responsibility of fixing this issue onto all projects that need to include this .fp. I'm guessing this is something you wanted to avoid. A better solution, in my mind is to have your .fp do all of the UI operations involving this .uir, including the LoadPanel call. From an architectural standpoint, you're better off putting all your related UI code in one place and then distribute it as a package. So, in this case, you could have the .fp load the panel, and it could do so by exporting an initialization-type function, which would essentially be a wrapper around the LoadPanel function call. This way, you force your client programs to really depend on your .fp, thus ensuring that the linker always pulls it in.

 

This was the first issue. I haven't really looked at your second zip file yet, but I'm going to now, and I'll post something a bit later.

 

Luis

Message 14 of 16
(1,625 Views)

Okay, I'm back.

 

So the samples2.zip issue was a bit more of a challenge, and it had me stumped for a while also. But in actually turns out that Markus Kossman, earlier in this thread had nailed this issue perfectly. It's a matter of link order. The CVI linker is single pass, and it links libraries before it links instrument drivers (.fp files). So, even though you added version.lib to the project, since none of the project files referenced the SDK functions, the linker essentially discarded version.lib. Then, sampleFP2.fp introduced a dependency on version.lib, but by then it was too late.

 

This is admitedly a major limitation in CVI that makes this type of use of an .fp file difficult. It is, of course, already difficult to use .fp files that have dependencies on third-party libraries to begin with, for the reasons that I had described earlier in the thread. But it's even more frustrating when you resign yourself to adding the .lib to the project manually and it still doesn't work!

 

Fortunately, there is one handy workaround for this type of issue. It's not primarily intended to address this scenario, but it can also be used to address this scenario: in your project, go to the Build>>Target Settings dialog, then select Enable LoadExternalModule, click on the Add Files to Executable button and then select version.lib from the list. This will instruct the linker to always include this library in the link, even if it doesn't have any outstanding references to it. This should solve the problem.

 

Luis

Message 15 of 16
(1,617 Views)

Hi Luis, thanks for your responses which gave me some more elements to understand the compiling / linking issues in CVI.

The workaround built on top of Enable LoadExternalModule effectively solves the issue about linking to SDK DLLs: this permits me to include in my instruments the limited subset of WinSDK calls that I repetedly use in my applications with the only effect of raising executable size by about 200K plus library size. I normally don't flag that checkbox when I don't need it to limit executable size but I have no problem in enabling it if it permits me to solve some problem.

 

As a side effect, if I compile my instrument into a static library and I add it to the list of modules to link I can have my common user interface callbacks included in the instrument and correctly linked without need to programmatically call them at least once to have them linked

 

 

I suppose the solution to my third problem (linking to third-party dlls) will go in this line too: I will double-check what happens to executable size as those dlls are often quite huge and since are not commonly used I will probably decide to leave them as effective DLLs to install separately on the concerned target machines.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 16 of 16
(1,571 Views)