Using .c and .cpp files in Visual Studio at the same time - c++

Trying to figure out how to get an application to compile that uses both C and C++ files. Not the entire code, but enough to get the idea:
main.cpp:
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include "one.h"
#include "two.h"
int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hInst2, LPSTR lpCmdLine, int nShowCmd) {
FunctionOne();
FunctionTwo();
}
one.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <gdiplus.h>
#include <gdiplusflat.h>
using namespace Gdiplus;
using namespace Gdiplus::DllExports;
int FunctionOne() {
}
two.c
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int FunctionTwo() {
}
The header files contain only definitions for those functions.
Now, if I compile this with a main.cpp, I get an "unresolved external symbol" for FunctionTwo. If I compile this with a main.c, I get the same thing for FunctionOne. Is this even possible, and if so, how would I set up the project to compile properly (Visual Studio 2010)?
It compiles fine if I comment out the alternate function depending on the extension for main.
Thanks!

The problem is two.h, it almost certainly wasn't written to allow a C++ compiler to properly compile the C function prototype. You'll want to take advantage of the predefined __cplusplus macro, like this:
two.h:
#ifdef __cplusplus
extern "C" {
#endif
int FunctionTwo();
// etc...
#ifdef __cplusplus
}
#endif
Lovely macro soup ;) If the header is pre-baked and never saw a C++ compiler before then do this in your .cpp source code file:
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include "one.h"
extern "C" {
#include "two.h"
}
Some programmers name their header files .hpp if they contain C++ declarations and .h if they contain C declarations. That's a pretty good practice I personally favor. So does the Boost team. It didn't otherwise set the world on fire.

C++ does name-mangling to support function overloading while C does not. You will have to mark your function as extern "C" to prevent name mangling.
// main.cpp
extern "C" int FunctionTwo();
.. the rest ..
// two.c
extern "C" int FunctionTwo() {
// stuff
}
See http://www.parashift.com/c++-faq/mixing-c-and-cpp.html for more information on mixing C and C++.

Related

vs2015 cuda9.0 linked SHA1_Init with CUDA implement instead of openssl cpu libs

I am a beginner to cuda, c++ and I am trying to move openssl sha1 cpu code to cuda c,but I ran into a weired problem.
here is the minimum code that can reproduce the problem.
There are three files in this vs2015 cuda9.0 project. They are main.cpp ,sha1.cu and sha1.h
//main.cpp
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "openssl\sha.h"
int main()
{
SHA_CTX ctx;
SHA1_Init(&ctx);
return 0;
}
//sha1.h
#ifndef SHA1_H
#define SHA1_H
#include <stdint.h>
#include <cuda_runtime.h>
namespace cudatest {
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
} SHA1_CTX;
#define SHA_CTX SHA1_CTX
#define SHA_DIGEST_LENGTH 20
__device__ void SHA1_Init(SHA1_CTX * context);
#ifdef __cplusplus
}
#endif
}
#endif /* SHA1_H */
//sha1.cu
#include <cuda_runtime.h>
#include "sha1.h"
namespace cudatest {
__device__ void SHA1_Init(SHA1_CTX * context)
{
}
}
The main.cpp uses C/C++ compiler and sha1.cu uses CUDA C/C++
And I add openssl headers into the AdditionalIncludeDirectories,set directory which contains ssleay32.lib and libeay32.lib to library path,set AdditionalDependencies with ssleay32.lib, libeay32.lib .
Then the project built with no error and no warning. But when I run it
or debug it,I found the function SHA1_Init runs into device code and
the program crashed immediately.
why the compiler linked function SHA1_Init with the cuda device
SHA1_Init implement which has a namespace cudatest wrapped instead
of a ssleay32.lib, libeay32.lib CPU implement?
OK,I found the problem.I shouldn't use extern "C" in a c++ namespace.It make the function visiable to the global namespace. if you define another c SHA1_Init function in a .cpp file ,the linker will complain.But if another SHA1_Init is in a openssl lib,the vs C/C++ linker warnned nothing but linked to the cuda implement.

extern "c" behaviour in linux platform

ScriptInterface.h
extern "C"
{
#include "kel.h"
#include "process.h"
#if defined(SIMULATOR_COMPILE_FROM_SCRIPTINTERFACE) || defined(SIMULATOR_WIN)
#include "sigtypes.h"
#endif
}
In windows platform this is not giving any errors(below code)
xyz.cpp
#include "kel.h"
#include "process.h"
#include "sigtypes.h"
#include "ScriptInterface.h"
Whereas it is giving 'Symbol look up error' in Linux platform. Is there any different behavior of extern 'C' in Linux platform?
_Z16KEL_MEM_AllocateP19KEL_MEM_tPoolHandlej is very much a mangled name and it's almost certainly there because you're including kel.h outside of the extern "C" block.
Get rid of the first three includes in xyz.cpp and just use the ones you include from within ScriptInterface.h (which are marked as non-mangling).

C++ access function from C DLL/lib

I'm desperately trying to access a DLL supplied with some hardware. I have the DLL, the LIB file and the headers for the DLL.
I first tried using C# but failed due to the large data structures that are passed around. I got the functions called but the values in the structures that are modified are not correct.
I then thought about writing a wrapper class in C++ and use this as a library for C#. But again here I can call the function but if I tested an signed long that is passed it is "1072955392l" instead of "-1l".
I then just renamed the cpp file to ".c" and compiled it again. Now I get the correct value.
Are there some differences in the datatypes from C to C++?
The functions for the LIb in the supplied include file are declared like that:
_declspec (dllimport) long ResetControl(Registers* regs);
I compile using VS2013:
cl test.cpp /link test.lib
cl test.c /link test.lib
The cpp file and c file are the same unless I needed to include #include for the cpp and wrap the dll include header in
extern "C"
{
#include "test.h"
}
The test.c file looks like:
//#include <windows.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#include <math.h>
#include "test.h"
int main (int argc, char **argv)
{
Registers Regs;
Reset (&Regs);
printf ("Value: %dl\n\r", Regs.Product);
return 0;
}
The C++ file:
#include <windows.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#include <math.h>
extern "C"
{
#include "test.h"
}
int main (int argc, char **argv)
{
Registers Regs;
Reset (&Regs);
printf ("Value: %dl\n\r", Regs.Product);
return 0;
}
Both compile, but the result of printing Regs.Products is different:
C: -1l
C++: 1072955392l
What am I doing wrong here?
I saw somewhere that there is a matter of aligning to 4 bytes while compiling the client of the DLL.
However have a look to those pages:
http://www.codeproject.com/Articles/21/Beginner-s-Tutorial-Calling-Visual-Basic-ActiveX-D
http://www.codeproject.com/Articles/6242/Step-by-Step-Calling-C-DLLs-from-VC-and-VB-Part
Alexandre

C++ lnk2005 error on two files with extern "C", why?

I have a CPP with extern "C" functions. If they are all in a single file, everything works great. I want to split up the functions into different files just for organizational purpose.
So lets say I have these two files:
File_One.cpp
#pragma once
#include "stdafx.h"
#include <windows.h>
#include "Functions.h"
#include "Variables.h"
#include <string>
#include "File_Two.cpp"
extern "C"
{
__declspec(dllexport) void MethodOne()
{
MethodTwo();
}
}
File_Two.cpp
#pragma once
#include "stdafx.h"
#include <windows.h>
#include "Functions.h"
#include "Variables.h"
#include <string>
extern "C"
{
__declspec(dllexport) void MethodTwo()
{
}
}
I have tried rearranging my include headers in different order, and even place no include headers in file_one.cpp other than the include for file_two.cpp but I always get the same errors.
1) error LNK1169: one or more multiply defined symbols found
2) error LNK2005: _MethodTwo already defined in File_One.obj
What exactly am I doing wrong?
What should I do to fix it?
Thank you!
You're probably running into issues because you're including the File_two.cpp file in your File_one.cpp file. What is happening is that File_two.cpp and File_one.cpp are getting compiled and linked. But because File_two.cpp is included in File_one.cpp, the linker is seeing two copies of MethodTwo, and can't decide which to use.
You should move the declarations to a header:
File_two.h:
extern "C"
{
__declspec(dllexport) void MethodOne()
}
And include that instead.
File_one.h:
extern "C"
{
__declspec(dllexport) void MethodOne();
}
Then define the functions with their body in their respective .cpp files. No need for extern "C" in the source files.

GetCurrentConsoleFont not declared in scope, what I do wrong?

at the beginning I have:
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <iomanip>
#include <string>
#define _WIN32_WINNT 0x500 //tells that this is win 2000 or higher, without GetConsoleWindow would not work
#include <windows.h>
using namespace std;
int main() {
PCONSOLE_FONT_INFO lpConsoleCurrentFont;
GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), false, lpConsoleCurrentFont);
return 0;
}
And undocumented function SetConsoleFont works, but GetCurrentConsoleFont fails at compilation saying that it was not declared in this scope.
-- edit: changed to self sustained code.
GetCurrentConsoleFont is exported on NT4+ at least, the MinGW headers must be wrong.
Try adding this code after your #include's:
#ifdef __cplusplus
extern "C" {
#endif
BOOL WINAPI GetCurrentConsoleFont(HANDLE hConsoleOutput,BOOL bMaximumWindow,PCONSOLE_FONT_INFO lpConsoleCurrentFont);
#ifdef __cplusplus
}
#endif
Your code is also wrong, it should be:
CONSOLE_FONT_INFO ConsoleFontInfo;
GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), false, &ConsoleFontInfo);
(Any time you see PSOMETYPE as a parameter you usually allocate a SOMETYPE struct on the stack and pass a pointer to this struct as the parameter)
Hans comment above is correct. GetCurrentConsoleFont is not defined in wincon.h. Add the following lines to wincon.h to get this functionality:
BOOL WINAPI GetCurrentConsoleFont(HANDLE, BOOL, PCONSOLE_FONT_INFO );
COORD WINAPI GetConsoleFontSize( HANDLE, DWORD );
GetConsoleFontSize was also missing.