LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Same lib on Win and Linux ?

Hello all,

I'm sure I've done this before but I just can't remember how.

I want to use a library that exists both in Windows and Linux for the two versions of my CVI project. For instance libusb (a system lib on Linux, a manual install on Windows).

 

If I add the libusb.lib file to the cvi project on Windows, it compiles and runs fine, but then upon compiling on Linux with "cvicc -lusb test.prj" I get gcc: /.../libusb-win32-bin-1.2.6.0/lib/msvc/libusb.lib: No such file or directory

If I remove the lib from the project, it compiles and runs fine on Linux but fails on Windows with error: Undefined symbol '_usb_claim_interface' referenced in "l:\test\cvibuild.test\Debug\test.obj"

 

So how can I include the lib file in the Windows build but exclude it from the Linux build ? Actually this should be the default as I don't see how a lib file could work on both.

 

Thanks

0 Kudos
Message 1 of 9
(5,150 Views)

If I understand your question correctly, this is typically done by using predefined OS compiler macros. Here are a couple of examples showing how to do this:

 

Detect Windows or Linux in C, C++

http://stackoverflow.com/questions/8666378/detect-windows-or-linux-in-c-c

 

 

Because there are typically multiple possible macros for the same OS, you will probably want to use logcal ORs to check all possible cases:

 

Determine if Linux or Windows in C++

http://stackoverflow.com/questions/3213037/determine-if-linux-or-windows-in-c

 

Here is a pretty extensive list of predefined macros you can use to determine the possibilities:

 

Pre-defined Compiler Macros

http://sourceforge.net/p/predef/wiki/OperatingSystems/

 

Thanks,

 

 

Regards,
0 Kudos
Message 2 of 9
(5,105 Views)

Thank you for the answer, but since it's a linker issue I don't think you can solve it by using compiler defines.

 

I've created a workaround by calling a script that removes the section of the .prj file that contains the .lib, and then send the patched project to cvicc. Sees to work but not very clean. I would think cvicc intelligent enough to ignore Windows only libraries ! Maybe this should be a bug report.

0 Kudos
Message 3 of 9
(5,077 Views)

You should be able to use #ifdef statements to conditionally load the library using the Win32 API call to LoadLibrary.  Documentation on the function can be found below:

 

How Can I Access DLL Functions in a LabWindows™/CVI Program Without Including the Import Library in the Project?

http://digital.ni.com/public.nsf/allkb/8AE57BDA995ACCB486256AEA0062B3C6

LoadLibrary function

https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx

 

There is also an example of how to use the Windows SDK in CVI located in <CVI>\Samples\sdk folder (where <CVI> is the installation directory of CVI).

 

Using this along with the predefined compiler macro for your operating system should do exactly what you want.

 

The code would resemble:

 

#ifdef(WINDOWS_OS_MACRO1 | WINDOWS_OS_MACRO2)

 

LoadLibrary(windows_usblib)

 

#endif

 

 

Thanks

Regards,
Message 4 of 9
(5,055 Views)

Hmmm, OK, so you can selectively load a DLL (I wanted a simple static lib, but okay), but then with CVI don't you have to link with a DLL import library, in other words, a static lib ? It kind of defeats the purpose...

 

Or do you use a DLL import source file ? And find a way to not compile it on the Linux side...

0 Kudos
Message 5 of 9
(5,038 Views)

Dynamically linking to a DLL via LoadLibrary+GetProcAddress does not require you to have a .lib file in the project: you simpy need a #include file that gives the definitions of the DLL functions.

Here is when preprocessor macros come in handy:  you may enclose the calls to the windows version in some #ifdef _WINDOWS or #ifdef _NI_mswin_ clause.

 

The boring part of this is to create the #include file that typedefs all the functions you need in your program. Just as an example, these are the definition of functions used by a APPLICOM communications board:

BOOL _stdcall IO_Init (WORD wCard, short *status);
BOOL _stdcall IO_Exit (WORD wCard, short *status);

Here is how you need to declare them to call them in the DLL:

typedef BOOL _stdcall (*INIT)(WORD, short *);
INIT IO_Init, IO_Exit;

If the translation is correct, you can then call the function in your code as if they where statically linked, after getting their address:

// Getting function addresses
hinstLib = LoadLibrary ("AppIO");
IO_Init = (INIT) GetProcAddress (hinstLib, "IO_Init");
IO_Exit = (INIT) GetProcAddress (hinstLib, "IO_Exit");

// Calling the functions
IO_Init (board, &sts);

 



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?
Message 6 of 9
(5,031 Views)

An alternative would be to just manage two projects - one for linux and one for windows.  If you're not adding and removing items from your projects a lot, this is a simple and very manageable solution

 

 

Regards,
Message 7 of 9
(5,024 Views)

You could  use a  custom build configuration to make the same project work for both Windows & Linux. In the custom build config mark the import libary as being excluded from the build (rt-click the lib in the project tree). When building on linux, use the -config=__NameOfConfig__ option to specify the custom config to cvicc.

 

I've written CAR 537857 to fix this in the next release of CVI for Linux.

 

Michael

NI

Message 8 of 9
(4,990 Views)

Thanks all. I've given kudoes to everyone because you all offer different working solutions. I'm going with the 'manage 2 projects' option, with a simple script to tronsform the Windows prj into a Linux one:

 

# Remove the Windows library from the MyProj.prj project file for the Linux compilation
Section=$(grep -B1 '^File Type = "Library"' MyProj.prj | head -1 | tr -d "\[\][:cntrl:]")
sed -e "/$Section/,+11 d" MyProj.prj > MyProjLinux.prj
0 Kudos
Message 9 of 9
(4,970 Views)