//lib.h
#pragma once
#ifdef _MSC_VER
#ifdef BUILD_LIB
#define LIB_API __declspec(dllexport)
#else
#define LIB_API __declspec(dllimport) /* here */
#endif
#else
#define LIB_API
#endif
void LIB_API boo();
class LIB_API foo {
public:
int bar() {
static int a = 0;
return a++;
}
};
//lib.cpp
#include "lib.h"
void boo() {
foo f;
f.bar();
}
// main.cpp
#include <cstdio>
#include "lib.h"
int main(int argc, char** argv) {
foo f;
boo();
printf("%d\n", f.bar());
return 0;
}
For MSVC, without __declspec(dllimport) it appears the variable has multiple instances - the output is 0. Otherwise the output is 1.
When foo::bar is defined in lib.cpp, even without __declspec(dllimport), the output is 1.
I'm not familiar with how other compilers handle exporting and importing symbols, but by default with:
g++ -shared lib.cpp -o lib.so
g++ main.cpp -L . lib.so
./a.out
The output is 1.
Is it possible that with certain options, g++ will behave like MSVC, that is, producing multiple instances of a?
Does the standard say anything about how functions defined in-class shall be instantiated, and does it have anything to do with how compilers handle static variables declared inside?
cppreference says:
Function-local static objects in all definitions of the same inline
function (which may be implicitly inline) all refer to the same object
defined in one translation unit.
I guess it's not otherwise guaranteed whatsoever.
Related
#include <string>
#include <sstream>
#include <iostream>
extern "C" {
struct A {
public:
#ifdef __cplusplus
//extern "C++" {
template<typename T>
T to_string(T value) {
return value;
}
//}
#endif /* __cplusplus */
};
}
int main() {
A a;
std::cout << a.to_string<int>(1);
return 0;
}
How to handle situation like this to keep the main function can execute correctly?
To make struct A able to use its member function.
Since it seems unable to use extern "C++" in a struct and it will report error templates must have C++ linkage currently.
dcl.link All functions and variables whose names have external linkage and all function types have a language linkage.
Class types do not. Wrapping a struct in extern "C" has no effect.
dcl.link Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved.
You should just #ifdef out C++-specific parts of your struct, such as access specifications and member functions, and hope (or find in the platform documentation) that your C compiler produces a struct with the layout identical to that produced by the C++ compiler.
struct A {
#ifdef __cplusplus
public:
template<typename T>
T to_string(T value) {
return value;
}
#endif /* __cplusplus */
};
Please consider the following code:
Test2.h:
#ifndef ABCD
#define ABCD
#ifdef __cplusplus
extern "C" {
#endif
void Foo();
#ifdef __cplusplus
}
#endif
#endif // ABCD
Test2.cpp
#include "StdAfx.h"
#include "Test2.h"
inline void Foo()
{
}
Test.cpp:
#include "stdafx.h"
#include "Test2.h"
int _tmain(int argc, _TCHAR* argv[])
{
Foo();
return 0;
}
When I compile this code I get LNK2019 error (Unresolved external symbol _Foo).
I can solve it in two ways.
Remove the inline keyword.
Add extern to the function declaration.
Assuming I want this function inline, why do I have to add extern to the declaration?
I use VS2008.
Thanks.
C++11 Standard Paragraph 3.2.3:
An inline function shall be defined in every translation unit in which it is odr-used.
You have 2 translation units, first made from Test2.cpp...:
// ... code expanded from including "StdAfx.h"
extern "C" { void Foo(); }
inline void Foo() { }
...and second made from Test.cpp:
// ... code expanded from including "StdAfx.h"
extern "C" { void Foo(); }
int _tmain(int argc, _TCHAR* argv[])
{
Foo();
return 0;
}
In the second TU, the definition of Foo is missing.
Why don't you simply put the definition of Foo into the header file? Compiler cannot inline its code if it does not see it.
Instead of writing each function in " extern "C" {} ", can I write entire header file inside that block.
extern "C"
{
#include "myCfile.h"
}
I have tried this but Its not working at all, why it is not working ?
if we have to use 100 C functions in a c++ project, do we need provide all the functions in a
extern block, is there any other simple way ?
Ex:
extern "C"
{
void fun1();
void fun2();
void fun3();
void fun4();
void fun5();
.
.
.
.
fun100();
}
Is there any other simple way, like extern "C" { myCfunctions.h } ???
#include simply includes the specified header at the location of the #include. Whether it's valid depends on what "myCfile.h" contains. In particular, including any standard library headers in such a context is not valid, and may well break on commonly used implementations.
The usual way to handle this is to make the header itself safe to use from C++. A C-only header might contain
#ifndef H_MYCFILE
#define H_MYCFILE
#include <stddef.h>
void mycfunc1(void);
void mycfunc2(int i);
void mycfunc3(size_t s);
#endif
Adapting this to make it safe to use from C++:
#ifndef H_MYCFILE
#define H_MYCFILE
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void mycfunc1(void);
void mycfunc2(int i);
void mycfunc3(size_t s);
#ifdef __cplusplus
}
#endif
#endif
With such a header, you wouldn't be able to safely put the entire header in an extern "C" block. However, that header itself can make sure not to put #include <stddef.h> in an extern "C" block, but still to put all function declarations in a single extern "C" block, avoiding having to repeat it for each one.
You are doing something wrong.
Because
extern "C" { myCfunctions.h }
should work. See below sample program.
Lets go by example code.
ctest1.c
#include<stdio.h>
void ctest1(int *i)
{
printf("This is from ctest1\n"); // output of this is missing
*i=15;
return;
}
ctest2.c
#include<stdio.h>
void ctest2(int *i)
{
printf("This is from ctest2\n"); // output of this is missing
*i=100;
return;
}
ctest.h
void ctest1(int *);
void ctest2(int *);
Now lets make c library from that
gcc -Wall -c ctest1.c ctest2.c
ar -cvq libctest.a ctest1.o ctest2.o
Now lets make cpp based file which will use this c apis
prog.cpp
#include <iostream>
extern "C" {
#include"ctest.h"
}
using namespace std;
int main()
{
int x;
ctest1(&x);
std::cout << "Value is" << x;
ctest2(&x);
std::cout << "Value is" << x;
}
Now lets compile this c++ program with C library
g++ prog.cpp libctest.a
Output is :
Value is15Value is100
I have a header file that declares a class, and I want this class to access an integer that has been declared in the main cpp C++ file (i.e. another file than the class' one). I have been searching on Google and found nothing relevant. How can I do this?
To share a global variable among source files, use the extern keyword.
main.cpp
#include "foo.h"
int global_var=0;
int main()
{
foo();
return 0;
}
foo.h
#ifndef FOO_H
#define FOO_H
extern int global_var;
void foo();
#endif
foo.cpp
#include "foo.h"
int foo()
{
global_var=1;
}
Move the integer in main.cpp into a function, make it static there, have the function return a reference to it and put the function into a header file of its own which the class header file (or implementation file, if appropriate) includes.
integer.h:
#ifndef INTEGER_H // use some better, longer name here
#define INTEGER_H
int &Integer();
#endif
integer.cpp:
#include "integer.h"
int &Integer()
{
static int i = 0;
return i;
}
Access the integer like this:
int x = Integer(); // copy
Integer() = 123; // assign
We have a large project with C and C++ code.
For every C++ implementation, apart from the C++ header, we usually have provide a C-header to allow functionality to be available for .c files, also.
So, most of our files look like so:
foo.hpp:
class C {
int foo();
};
foo.h:
#ifdef __cplusplus
extern "C" {
typedef struct C C; // forward declarations
#else
class C;
#endif
int foo( C* ); // simply exposes a member function
C* utility_function( C* ); // some functionality *not* in foo.hpp
#ifdef __cplusplus
}
#endif
foo.cpp:
int C::foo() { /* implementation here...*/ }
extern "C"
int foo( C *p ) { return p->foo(); }
extern "C"
C* utility_function ( C* ) { /* implementation here...*/ }
QUESTION:
Suppose I wanted to add a namespace to the class like so:
foo.hpp:
namespace NS {
class C {
int foo();
};
}
what is the best scheme to follow in the C-headers?
I have considered a few options, but I'm looking for the most elegant, safe and easy to read. Is there a standard way you use?
Here are the options I've considered:
(I've ommitted the extern "C" constructs for simplicity)
Option 1: fool the compiler by adding some code in each header:
foo.h
#ifdef __cplusplus
namespace NS { class C; } // forward declaration for C++
typedef NS::C NS_C;
#else
struct NS_C; // forward declaration for C
#endif
int foo( NS_C* );
NS_C* utility_function( NS_C* );
this adds some complexity to the header, but keeps the implementations unchanged.
Option 2: Wrap the namespace with a C-struct:
Keeps the header simple but makes the implementation more complex:
foo.h
struct NS_C; // forward declaration of wrapper (both for C++ and C)
int foo( NS_C* );
NS_C* utility_function( NS_C* );
foo.cpp
namespace NS {
int C::foo() { /* same code here */ }
}
struct NS_C { /* the wrapper */
NS::C *ptr;
};
extern "C"
int foo( NS_C *p ) { return p->ptr->foo(); }
extern "C"
NS_C *utility_function( NS_C *src )
{
NS_C *out = malloc( sizeof( NS_C ) ); // one extra malloc for the wrapper here...
out->ptr = new NS::C( src->ptr );
...
}
are these the only schemes? Are there any hidden disadvantages in any of these?
I find it easier to factor code in a way so that foo.h only contains the bare minimum of C++ specifics while foo.hpp takes care of the gritty bits.
The file foo.h contains the C API and should not be included directly from C++ code:
#ifndef NS_FOO_H_
#define NS_FOO_H_
// an incomplete structure type substitutes for NS::C in C contexts
#ifndef __cplusplus
typedef struct NS_C NS_C;
#endif
NS_C *NS_C_new(void);
void NS_C_hello(NS_C *c);
#endif
The file foo.hpp contains the actual C++ API and takes care of including foo.h into C++ files:
#ifndef NS_FOO_HPP_
#define NS_FOO_HPP_
namespace NS {
class C {
public:
C();
void hello();
};
}
// use the real declaration instead of the substitute
typedef NS::C NS_C;
extern "C" {
#include "foo.h"
}
#endif
The implementation file foo.cpp is written in C++ and thus includes foo.hpp, which also pulls in foo.h:
#include "foo.hpp"
#include <cstdio>
using namespace NS;
C::C() {}
void C::hello() {
std::puts("hello world");
}
C *NS_C_new() {
return new C();
}
void NS_C_hello(C *c) {
c->hello();
}
If you do not want to make the C API available to C++ code, you could move the relevant parts from foo.hpp to foo.cpp.
As an example for use of the C API a basic file main.c:
#include "foo.h"
int main(void)
{
NS_C *c = NS_C_new();
NS_C_hello(c);
return 0;
}
This example has been tested with the MinGW edition of gcc 4.6.1 using the following compiler flags:
g++ -std=c++98 -pedantic -Wall -Wextra -c foo.cpp
gcc -std=c99 -pedantic -Wall -Wextra -c main.c
g++ -o hello foo.o main.o
The code assumes that the types NS::C * and struct NS_C * have compatible representation and alignment requirements, which should be the case virtually everywhere, but as far as I know is not guaranteed by the C++ standard (feel free to correct me if I'm wrong here).
From a C language perspective, the code actually invokes undefined behaviour as you're technically calling a function through an expression of incompatible type, but that's the price for interoperability without wrapper structures and pointer casts:
As C doesn't know how to deal with C++ class pointers, the portable solution would be to use void *, which you should probably wrap in a structure to get back some level of type safety:
typedef struct { void *ref; } NS_C_Handle;
This would add unnecessary boilerplate on platforms with uniform pointer representation:
NS_C_Handle NS_C_new() {
NS_C_Handle handle = { new C() };
return handle;
}
void NS_C_hello(NS_C_Handle handle) {
C *c = static_cast<C *>(handle.ref);
c->hello();
}
On the other hand, it would get rid of the #ifndef __cplusplus in foo.h, so it's actually not that bad, and if you care about protability, I'd say go for it.
I don't fully understand what you're trying to do, but this may help:
If you want it still accessible by C then do this:
void foo();
namespace ns {
using ::foo;
}
Or use a macro:
#ifdef __cplusplus
#define NS_START(n) namespace n {
#define NS_END }
#else
#define NS_START(n)
#define NS_END
#endif
NS_START(ns)
void foo();
NS_END
Your header is all messed up.
You probably want something more like:
struct C;
#ifdef __cplusplus
extern "C" {
#else
typedef struct C C;
#endif
/* ... */
#ifdef __cplusplus
}
#endif