LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

unresolved external symbol __GetErrno and __GetFilesArray

I am trying to build my CVI project in MSVC. As I am using toolbars, I have included toolbar.obj and tollslib.obj (probably required by toolbar.obj). Now I am left with two unreolved symbols __GetErrno and _GetFilesArray. I am giving the linker error message below. Pleas help me out.

Thanks and Regards,
Kantha Rao


--------------------Configuration: VCApplic - Win32 Debug--------------------
Linking...
Creating library VCApplic.lib and object VCApplic.exp
LINK : warning LNK4098: defaultlib "LIBC" conflicts with use of other libs; use /NODEFAULTLIB:library
toolbox.obj : error LNK2001: unresolved external symbol __GetErrno
toolbox.obj : error LNK2001: unresolved external symbol __GetFilesArray
V
CApplic.dll : fatal error LNK1120: 2 unresolved externals
Error executing link.exe.

VCApplic.dll - 3 error(s), 1 warning(s)
0 Kudos
Message 1 of 10
(6,545 Views)
Kantha,

The common C run-time library is implemented by both CVI and VC. Since the exports defined by this library are universal (they're defined by the ANSI standard) any code that is written in CVI or in MSVC can, in theory, be compiled by either compiler, and the end result is the same. The way things are supposed to work is that when you take your CVI application to MSVC, every library call is linked to the CVI run-time libraries (cvirt.lib, etc...) except for calls made to the CVI ANSI C library. Those become linked to VC's equivalent library. The problem here is that two of the exports of this library are implemented as macros: errno and stdout. (There are other macros, but these are the ones that are causing the problem). These macros are defined in CVI as calls to _GetErrno and _GetFilesArray respectively (you can see this in cvi\include\ansi\errno.h and cvi\include\ansi\stdio.h). However, in MSVC they are defined differently. The end result is that if you take a file to MSVC that has *already* been compiled in CVI, you get link errors, since the CVI-specific functions are missing from the VC library. However, if you take that same file and compile it in MSVC, it will work, because it will then be using the MSVC definition of those macros.

What is the implication of this? It means that you cannot take an object file that has been compiled in CVI into a MSVC project, if that object file uses either of these symbols. That is the case with toolbox.c. In your case, toolbox.obj is being included because toolbar.fp depends on it.

You can solve the problem by doing one of two things: 1) replace toolbox.obj in your MSVC project with toolbox.c, or 2) create a stub file containing the following functions, and link to it from your MSVC project:

#include "errno.h"
#include "stdio.h"

static FILE *wrapper_files[3] = {stdin, stdout, stderr};

int _GetErrno (void)
{
return errno;
}

FILE **_GetFilesArray (void)
{
return wrapper_files;
}

Hope this helps.

Luis
NI
Message 2 of 10
(6,546 Views)
This has fixed my problem. Thank you very much.
0 Kudos
Message 3 of 10
(6,545 Views)

That works great!  Do you have some similar magic for GetDoubleEps and GetDoubleMin from float.h?

Thanks,

locolobo

0 Kudos
Message 4 of 10
(6,402 Views)
By far the best solution, and also the easiest, is to port the .c file to VC and make sure that VC compiles it. Don't try to port the .obj file.
 
While it is possible to write stubs for those two symbols, they are going to be more difficult than the other two because of the .val indirection (check the definitions of DBL_MIN in the CVI version of float.h, and then in the VC version of float.h, and you can see what I mean)
 
Luis
0 Kudos
Message 5 of 10
(6,394 Views)

I wish I could bring in the source, but it is "proprietary" and only being provided in a .lib.

As I was experimenting with a solution for the _GetDoubleMin, I noticed that the _GetFilesArray solution only seemed to work when the CVI stdio.h file was used for the compilation of the stub file.  Is that the expected situation?

Thanks.

0 Kudos
Message 6 of 10
(6,391 Views)

That is not the expected situation. It is intended to work with the MSVC version of stdio.h (at least, the 7.1 version of the compiler, if I remember correctly). But if you are having problems, this illustrates why creating these stubs is not ideal. They assume too much about how the particular target compiler that you are using implements these ANSI C symbols. The ANSI spec only requires that these particular symbols be available in the library, and also specifies their behavior, but does not specify how they should be implemented. These will work as long as you use the same compiler to compile and link the module. But if you change the compiler between the compilation stage and the linking stage, then problems can happen.

What happens is that each compiler ends up implementing these symbols in its own way, and those stubs are probably assuming too much about the implementation in a particular compiler.

I understand that in this particular case you do not have access to the source code, and that you need to build your project in a compiler other than CVI. If the .lib file was created by the CVI compiler, it will link just fine in CVI. Therefore, have you considered wrapping the exports you need from the .lib file into a DLL, that you can build in CVI, and then call from the project that you are building in the other compiler?

Luis

0 Kudos
Message 7 of 10
(6,371 Views)

I think that I may have it working.  I needed the 'extern "C"' to get past using the CVI stdio.  I'm no longer getting linker errors, but I have yet to test the entire package to ensure that it all still works properly.  Below is the code I am using.  Feel free to comment.

#include "stdio.h"
#include "float.h"

#ifdef __cplusplus
    extern "C" {
#endif

#ifndef _DBL_CONST_T
#define _DBL_CONST_T
typedef const union {
    double val;
    unsigned char a[8];
} _DoubleConst_t;
#endif

static FILE *wrapper_files[3] = {stdin, stdout, stderr};
static _DoubleConst_t DoubleMin = {DBL_MIN};
static _DoubleConst_t DoubleEps = {DBL_EPSILON};

FILE **_GetFilesArray (void)
{
return wrapper_files;
}

_DoubleConst_t *_GetDoubleMin (void)
{
return &DoubleMin;
}

_DoubleConst_t *_GetDoubleEps (void)
{
return &DoubleEps;
}

#ifdef __cplusplus
    }
#endif

0 Kudos
Message 8 of 10
(6,376 Views)
Yes, that should work. The one thing I would have done differently would have been to use the actual constants that are in the VC header file, when initializing those variables:
 
static _DoubleConst_t DoubleMin = {2.2250738585072014e-308};
static _DoubleConst_t DoubleEps = {2.2204460492503131e-016};
 
The reason being that, if this code ever got compiled against the CVI version of float.h, you would not end up with a recursive definition for DBL_MIN and DBL_EPSILON.
 
But it should work, yes.
 
Luis
0 Kudos
Message 9 of 10
(6,343 Views)
This problem is actually caused by the order of the include file directories searched, make sure the CVI directories are last. I had one project that worked and one that didn't, I changed the order of the directories so that the CVI ones are last (like the working one) and the previously non-working one now works.
0 Kudos
Message 10 of 10
(5,424 Views)