I'm trying to install the NVIDIA version of a toolkit, and I'm getting error messages like "... this declaration may not have extern "C" linkage" - nvcc

I'm trying to install the NVIDIA version of an externally supplied toolkit (for the purposes of this message it doesn't matter what the toolkit is, this is a problem about how to use nvcc), and I'm getting error messages like "usr/include/c++/6/utility(329): error: this declaration may not have extern "C" linkage".
I'm not a C or C++ programmer, but I am happy enough poking around in things like Makefiles. I'm pretty sure that I've got all the paths set to point to the right places, and /usr/include/c++/6 contains all the files that are generating the error messages. But I have no idea what these error messages mean and what I should do to get round them.

I believe these errors are from C/C++ name mangling differences and the fact that NVCC compiles as a C++ compiler. I was able to compile HTK 3.5 by simply removing the extern "C" declarations from HCUDA.cu:
#ifdef __cplusplus
extern "C" {
#endif
/* ... */
#ifdef __cplusplus
}
#endif
I suspect that, because they're already declared extern "C" in HCUDA.h, they don't need to be declared such in HCUDA.cu, but I'm not sure.

Related

Visual C++ 2017, extern "C" ignored? LNK2019 errors when linking C++ code to C libraries

A solution has a project consisting of a static library (one .h file, one .c file) written in C, and a utility program (.cxx) based on that library written in C++.
The library compiles without error. The utility compiles too, but fails in linkage with errors like:
1>abc.obj : error LNK2019: unresolved external symbol "struct DEFListen * __cdecl DEFisten(int,char *,int)" (?DEFListen##YAPAU0#HPADH#Z) referenced in function _main
The header for the library includes extern "C" guards:
#ifdef __cplusplus
extern "C" {
#endif
By putting garbage inside the ifdef, I get compile warnings when compiling (not linking) the utility as expected, so I know __cplusplus is in fact defined when the utility is compiled, and not for instance merely misspelled.
Yet, the error message shows the function signature (and the mangled name) for the function in question. dumbin /symbols on the utility's object file of course confirms the object contains mangled symbols.
In summary: extern "C" { is definitely being parsed at compile time yet ignored. Why?
Problem is so stupid: is that the closing brace code (below) had been cut and pasted to an alternate location, while re-arranging declarations, leaving several functions outside the extern block.
#ifdef __cplusplus
}
#endif
Sorry I didn't spot that before posting for help.
I leave this shameful post to found by someone equally foolish (possibly me) in the future.

Is calling atoi without stdlib undefined behaviour?

Is calling atoi without including stdlib.h undefined behaviour?
I can't find where I have included stdlib.h in my project, even though I have used atoi.
The thing is actually atoi has been working fine - it has been parsing integers correctly every time the software has been used.
It is some embedded device.
So is there case this can be well defined?
btw. In this line:
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */
#include "sdkGlob.h"
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
that header includes stdlib.h but I can't understand in which case it is included. And I am not sure if this cplusplus is defined anywhere. This is a c project anyway.
Prior to C99 it was acceptable to use functions that hadn't previously been declared. The compiler might generate a warning but there would be no error until the linker either didn't find the function or found a function of the same name with a signature other than the one that the compiler had guessed. Luckily for you, the compiler always guesses a return type of int.
In C99 it became necessary for function declarations to be visible but not all compilers strictly enforce the rule.
As per Random832's comment, it's also quite possible that sdkGlob simply includes stdlib for itself.
As to your other question: sdkGlob is always included but if run through a C++ compiler rather than a C compiler you also get the extern "C"{ .. } wrapping. That tells the C++ compiler not to mangle the names so that you can link against a version of that module that was built using an ordinary C compiler. It's the normal way to provide plain C libraries in a way that allows them to be used by both C and C++ code.
The short answer
Two possibilities:
It's probable that sdkGlob.h include stdlib.h or define its own version of atoi.
Some compilers, like GCC, resolve missing #include and even hide the errors or warnings. Run gcc -Wall and check if warnings appears.
About ifndef
The #ifdef __cplusplus sections are used by C++ compilers. Here, you're saying '*if and if only the code is being compiled by a C++ compiler, do ... *'.
The C-only version of your code:
#include "sdkGlob.h"
The C++-only version of your code:
extern "C"{
#include "sdkGlob.h"
}

C - Generate warning when loosely defined function is called

I'd like to generate a compiler warning for a specific situation. I'm building a sort of universal code that will be built based on several pre-compiler definitions. For instance I might have something like the following.
sdcard.h
#ifdef PART_BOARD1
#include "port/board1.h"
#elif PART_BOARD2
#include "port/board2.h"
#endif
extern void sdcardConfigure(void);
sdcard.c
#ifndef FLAG_SDCARD
#warning "No SD Card available for this board, or this board has not been defined"
#define sdcardConfigure(...) void(0)
#endif
port/board1.h (similar for port/board2)
#define FLAG_SDCARD
void sdcardConfigure(void);
port/board1.c
void sdcardConfigure(void) {
// sd card is configured here
}
Essentially what I'd like to do is modify the #define sdcardConfigure(...) statement in sdcard.c so that I'm only seeing the warning message if sdcardConfigure() is actually called. Making it act like:
void sdcardConfigure(void) {
#warning "sdcardConfigure() not available on this board"
}
The idea being that this gives me the flexibility to create a universal (I know many fear universal) program that adapts to the parts that it's using. I.E. if there is an SD Card use it, otherwise generate a warning saying "you're calling a function that doesn't exist for this part" and let the developer decide if the function is needed.
The answer to this will most-likely be compiler-dependent.
For gcc et al you can use __attribute__ ((deprecated)) (see gcc manual).
For Visual Studio you can use __declspec(deprecated).

Clang C Compiler 'class' keyword reserved?

Hi I am compiling ffmpeg using xcode, which I believe uses clang for compilation. In ffmpeg there is a struct with a member variable named 'class' I believe this is perfectly fine in C but clang is trying to parse it as a keyword. Any idea how to fix? Basically the following in a cpp file will cause the error:
extern C {
typedef struct {
int class;
} SomeStruct;
}
It tries to interpret class as a keyword.
FYI the file that is throwing the error in ffmpeg is libavcodec/mpegvideo.h and I need to include this to have access to the MpegEncContext struct to pull out motion map info.
EDIT
The above code sample was just to demonstrate the error. But perhaps its fixable in another way. In my actual code I have it like this:
#ifdef __cplusplus
extern "C" {
#endif
#include "libavcodec/mpegvideo.h"
#include "libavformat/avformat.h"
#if __cplusplus
} //Extern C
#endif
How would I get that to include the two files as C files and not C++?
Thanks
It's completely fine in C. When you build that as C++, you encounter an error because class is a C++ keyword.
As far as fixing it, you would normally choose an identifier other than class. However, ffmpeg developers may not be so agreeable with that change. Therefore, you may need to either:
restrict the visibility of that header to C translations
or edit your own copy in order to use it in C++ translations
Fortunately, you are also using a C compiler which has good support of C99 features in this case. C Compilers which do not support C99 well are particularly troublesome with ffmpeg sources (because you would then compile the whole program as C++ for the C99 features, and the conflict count would be much higher).
(there are other dirty tricks you could do to try to work around the problem, but i will not mention them)
Basically the following in a cpp file will cause the error
.cpp files are processed as C++ files, not C, and class is a reserved word in C++.
If you don't have a choice to rename anything in those header files, you could just replace the class token by something else
#ifdef __cplusplus
extern "C" {
# define class videoClass
#endif
#include "libavcodec/mpegvideo.h"
#include "libavformat/avformat.h"
#if __cplusplus
# undef class
} //Extern C
#endif
This is quite a dirty hack, but for such badly interfaced code you don't have much choice. The real solution would be to have all the struct members in these files use names that us some sort of prefix or so, as it is done in the network layer code. There all members have some prefixes as ss_ or sa_ and such problems are very unlikely to occur.

Confused by Unresolved external symbol error

I'm trying to build a wrapper library with VC++'s compiler.
ErlDriver.c
#define __WIN32__
#define DLL_EXPORT __declspec(dllexport)
#include "erl_driver.h"
DLL_EXPORT int _driver_output(ErlDrvPort port, char *buf, int len) {
return driver_output(port, buf, len);
}
build.bat
cl /I%ERL_DRIVER_H% /LD /MD ErlDriver.c
When I attempt to build this, I get the following linker error:
ErlDriver.obj : error LNK2019: unresolved external symbol _WinDynDriverCallbacks referenced in function __driver_output
erl_win_dyn_driver.h (included in erl_driver.h)
typedef struct {
WDD_FTYPE(driver_output) *driver_output;
// a ton more of those
} TWinDynDriverCallbacks;
extern TWinDynDriverCallbacks WinDynDriverCallbacks;
#define driver_output (WinDynDriverCallbacks.driver_output)
So, as you can see, WinDynDriverCallbacks is defined declared.
What could be causing the linker error, then?
No, it's not defined (at least in what you quoted). It's declared. The "extern" keyword means "the definition for this symbol appears in another compilation unit (source file)." You need to be linking with the object file (or library) produced from compiling the source file that defines that symbol.
There is a subtle difference between "declaring" something and "defining" it in C or C++. When you declare it, it tells the compiler that a certain symbol will be defined somewhere else - this can allow the code to use that symbol without needing to see the actual definition. You still have to define the symbol somewhere in the code that is linked in, or else you will get the error message you are seeing.
For example, this is a declaration of the symbol WinDynDriverCallbacks:
extern TWinDynDriverCallbacks WinDynDriverCallbacks;
Your code has this declaration - it allows the code that uses the symbol to successfully compile (but not link).
You need to add a definition somewhere:
TWinDynDriverCallbacks WinDynDriverCallbacks;
The definition must go into a source code file somewhere (not generally in a header file). This tells the compiler to allocate space in the object code for that object and allows the program to link successfully.
I got a very similar problem building a NIF on Windows. Unresolved external symbol _WinDynNifCallbacks. Turns out this is defined by the ERL_NIF_INIT macro and in my case the entire macro needed to be enclosed in a extern C block.
ie this failed
extern "C" ERL_NIF_INIT(...)
while this succeeded
extern "C"
{
ERL_NIF_INIT(...)
}
I strongly suspect this problem is due to the same issue but with the DRIVER_INIT macro for an erlang port driver.
Driver_Init is the main loop that declares "TWinDynDriverCallbacks WinDynDriverCallbacks;" but it's properly declared in the multiple line define for driver_init. You shouldn't need to wrap it in extern "c".
since this thread came up about a million times while trying to setup my barebones erlang port driver i will say this here. I am working out of Joe Armstrong's programming erlang book, chapter 12 interfacing techniques. Using erl5.9 and vs2010.
The code in the book had a omission and a error in example1_lib.c. Though the error is most likely due to the age of the book versus erlang version changes.
Needed to set (#define WIN32) at the very top of example1_lib.c otherwise erlang defaulted to all the Linux options.
Second needed to change (int bufflen) to (ErlDrvSizeT bufflen) in example_drv_output.
After that it built clean.

Resources