Mixing C++ and C code - Linker issues in VS10 - c

I've got a problem mixing the C++ and C code. My C++ code was created in VS10, i.e is a Windows Form project. I want include my C function in my C++ function through of linker (.obj). The steps are:
Windows Form project
VS10 default project
Call the C function
Build the project manually using msbuild
C code
Build the project manually through a make file using nmake and generates the objects files (.obj)
With the every objects files in hands (Cpp and C), the objects are linked in a third makefile. It's a simple idea but it doesn't work. The build in msbuild show the following message:
error LNK2028: unresolved token (0A00000C) "extern "C" void __clrcall MinhaFuncao(void)" (?MinhaFuncao##$$J0YMXXZ) referenced in function "int __clrcall main(cli::array^)" (?main##$$HYMHP$01AP$AAVString#System###Z)
error LNK2019: unresolved external symbol "extern "C" void __clrcall MinhaFuncao(void)" (?MinhaFuncao##$$J0YMXXZ) referenced in function "int __clrcall main(cli::array^)" (?main##$$HYMHP$01AP$AAVString#System###Z)
The Cpp code:
#include "stdafx.h"
#include "Form1.h"
//#include"complex.h"
extern "C" {
#include "complex.h"
}
/*extern "C" {
void MinhaFuncao();
}*/
extern "C" void MinhaFuncao();
using namespace WFormTesting;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
MinhaFuncao(); //<--- Calling the Function HERE -->
// Create the main window and run it
Application::Run(gcnew Form1());
return 0;
}
The C code:
#include "complex.h"
void MinhaFuncao()
{
printf("My function AOWWW.\n");
}
The header file:
#ifndef COMPLEX_H_
#define COMPLEX_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
void MinhaFuncao();
#ifdef __cplusplus
} // extern "C"
#endif
#endif
Has someone got an idea about this problem? I read others posts about linker issues, but the solutions proposed don't work for me. I believe that the difference is due to the msbuild and the VS project... :/

You are using extern "C" in an extern C block
remove the outer extern C block surrounding
#include "complex.h"

Related

Create dynamic library using MSVC command line

I've read a lot of posts and yet I don't understand how to create a simple dynamic library on windows using MSVC in command line. What I'm doing is:
1º) Code the DLL
dynamic.h
#pragma once
__declspec(dllexport) void HelloWorld();
dynamic.c
#include "dynamic.h"
#include <stdio.h>
void HelloWorld(){
printf("Hello World");
}
2º) Compile it
cl /LD dynamic.c
(it compiles correctly and without errors generating dynamic.dll and dynamic.lib)
3º) Try to test it
main.c
#include<stdio.h>
#include"dynamic.h"
int main(){
HelloWorld();
return 0;
}
cl main.c dynamic.lib
ERROR (by cl.exe x64)
main.cpp
Microsoft (R) Incremental Linker Version 14.16.27034.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:main.exe
main.obj
.\dynamic.lib
main.obj : error LNK2019: unresolved external symbol "void __cdecl HelloWorld(void)" (?HelloWorld##YAXXZ) referred in main
main.exe : fatal error LNK1120: unresolved externals
Please teach me how dynamic libraries compilation really work because I can't understand
In main.c it needs to see the function declaration like this:
__declspec(dllimport) void HelloWorld();
So you cannot use the same dynamic.h as you currently have, for both building the DLL and building main.c .
Normally people will use a preprocessor setup so the same header file has a different declspec depending who is including it, for example:
// dynamic.h
#ifndef DLL_FUNCTION
#define DLL_FUNCTION __declspec(dllimport)
#endif
DLL_FUNCTION void HelloWorld();
dynamic.c (in the DLL):
#define DLL_FUNCTION __declspec(dllexport)
#include "dynamic.h"
Try this way in dynamic.h :
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) void HelloWorld();
#ifdef __cplusplus
}
#endif
Use 'dumpbin.exe /exports dynamic.dll' to show exported symbols

Void function declared in *.hxx, defined in *.cxx but undefined in *.c

I'm trying to declare a global function accessible through different *.c files.
I have declared it in param.hxx, defined it in param.cxx and I would like to access it in compute_grid.c.
Unfortunately, during the compilation I have the following error :
compute_grid.c:(.text+0x5) : undefined reference to « grid_create »
I'm not very familiar with such functions declarations in C. Actually I'm building a module part of a big program, I've copied those declaration from another file of the code witch seems to work ?!
Unfortunately, the program is hugely confidential, I don't have access to all the sources but I will do my best to give you expurged parts...
param.hxx :
typedef struct grid_t
{
int *test;
} grid_t;
void
grid_create(void);
extern grid_t *grid;
param.cxx :
#include <malloc.h>
#include "param.hxx"
grid_t *grid;
void grid_create(void)
{
grid = (grid_t*)malloc(sizeof(grid_t));
grid->test = (int*)malloc(sizeof(int));
*grid->test = 123;
}
compute_grid.c :
#include "param.hxx"
void
compute_grid()
{
grid_create();
return;
}
Thank you for your help !
.cxx is one of the extensions used for C++ files. Your compiler may be using the extension of the file to compile the source as C++. When the C file is compiled, it generates an unresolved reference to the C symbol grid_create, but the compiled C++ file defines grid_create as a C++ symbol. Thus, the linker will leave the C symbol reference to grid_create unresolved, since there is only a C++ symbol associated with void grid_create(void).
You can try to guard the header file so that the C++ compiler will generate a C symbol rather than a C++ one.
#ifdef __cplusplus
extern "C" {
#endif
void
grid_create(void);
#ifdef __cplusplus
}
#endif

How to call unadorned C++ function from C++/CLI

I've written a C++/CLI function which I can call from Fortran. It is specified as
extern "C"
{
void __declspec(dllexport) __cdecl someFunct(int val)
{
...
}
}
This works; it calls managed code, and I can call it from Intel Visual Fortran. When I dumpbin the DLL, I see that it is exported as _someFunct
I now want to call this function from another C++/CLI DLL. I've tried the following spec (with and without a leading underscore), but both fail the same way:
extern "C" extern __declspec(dllimport) void __cdecl someFunct(int val);
The error message I get is this:
Error 4 error LNK2028: unresolved token (0A00000A) "extern "C" void __cdecl someFunct(int)" (?someFunct##$$J0YAXH#Z) referenced in function "public: void __clrcall NUnitTesting::Class1::Test(void)" (?Test#Class1#NUnitTesting##$$FQ$AAMXXZ)
It seems the linker expects an adorned name, even though I specify extern "C" in the spec. How can I force the name to be unadorned?
Figured it out. My spec has to be preceeded by name of DLL:
using namespace System::Runtime::InteropServices;
[DllImport("DLL_with_someFunct",CallingConvention=CallingConvention::Cdecl)]
extern "C" extern void __cdecl someFunct(int val);

namespace and extern 'C' compilation errors

I have tried to google the errors but to no avail. Maybe I am searching in the wrong direction.
I am trying to compile a file but when i tired to compiled it, the compiler gave me these errors:
C2059 syntax error: ';'
C2059 syntax error: '}'
C2061 syntax error: identifier 'namespace_name'
C2449 syntax error: found '{' at file scope (missing header?)
In my code.c file:
#ifndef myclass_c
#define myclass_c
#include "classA.h"
#include "classB.h"
#include "conversionLib.h" // no namespace is being used here
namespace namespace_name {
// ... generated codes in C....
}
#endif
In classA.h and in classB.h:
#ifndef myclassA_h // myClassB_h if in classB
#define myclassA_h // myClassB_h if in classB
#include "classC.h" // both classA and classB include classC.h
namespace namespace_name {
#ifdef __cplusplus
extern "C" {
#endif
// ... generated codes in C....
#ifdef __cplusplus
}
#endif
}
#endif
and in classC.h (same for classD.h)
#ifndef myclassC_h // myclassD.h for classD.h
#define myclassC_h // myclassD.h for classD.h
#include "classD.h" // no includes in classD.h
namespace namespace_name {
#ifdef __cplusplus
extern "C" {
#endif
// ... generated codes in C....
#ifdef __cplusplus
}
#endif
}
#endif
what am i doing wrong? or have i missed out something?
Any suggestion would be greatly appreciated.
I apologized if this question/format is confusing.
Thanks in advance
The main problem seems to be, that you use c++ syntax in a .c file.
C does not support namespaces!
It does not make much sense to put a extern "C" function into an namespace. in C++ the compiler does something called 'name mangeling' it actually puts the name space (e.g. the class name, the namespace) and additional information (like function or template parameter) of an identifier into its symbol name that is the input to the linker.
extern "C" tells the C++ Compiler not to do so. so you lose the binding to the surrounding namespace (as well as the possibilities to overload the function).
It may be a nice thought to put the functions in a special namespace if they are included from C++ but on the other hand mostly in C namespaces are build y using a special prefix to the function name. so in C++ you end up with the explicit c++ name space and the implicit function prefix name space.
If you still want a namespace in c++ around your C-Functions you have to include the namespace definition into your #ifdef __cplusplus blocks. (but i do not even know if this is allowed by the C++ standard)

C / CUDA implementation with external variables produces linker error (unresolved external symbol)

I have a C-Project, which I would like to boost using a CUDA-module. But somehow, the externally defined variables can not be resolved. I am using Microsoft Visual C++ 2010 Express and CUDA Toolkit 5.0.
The following shows my minimal (not) working example:
main.c:
#include "main.h"
#include <stdio.h>
#include "cuda_test.cu"
int main( int argc, const char* argv[] )
{
testfunc();
return 1;
}
main.h:
#ifndef main_h
#define main_h
extern float PI;
#endif
testfile.c:
#include "main.h"
float PI = 3;
cuda_test.cu:
#include "main.h"
#include <stdio.h>
void testfunc()
{
printf("Hello from cudafile: %E", PI);
}
This yields the following error:
1>------ Build started: Project: cuda_min, Configuration: Debug Win32 ------
1>cuda_test.cu.obj : error LNK2001: unresolved external symbol "float PI" (?PI##3MA)
1>D:\Backup\diplomarbeit\cuda_xanthos\cuda_min\Debug\cuda_min.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
When passing the variable PI to the function testfunc, I get the desired behavior. This is what I am doing in my project (which actually uses the CUDA-device), but I really do not want to pass about 20 variables to my functions.
I suppose I am missing some setting for nvcc...
Any help would be much appreciated.
.cu is compiled and linked as .cpp, not .c. So, you can either rename your .c files to .cpp, or use extern "C" in your .cu file.

Resources