Is friend resolved entirely during the typechecking phase, or does it affect the way the output code is generated? In other words, is that possible that adding a friend to my class can result in a different binary file?
If it might be up to the compiler, then I am asking about GCC and Clang.
It's easy enough to test using GCC:
Let's create a simple program
#include <iostream>
class A {
private:
void print()
{
std::cout << "Hello" << std::endl;
}
};
class B {
public:
// friend class A; //Uncomment to make a friend!
void print()
{
std::cout << "World!" << std::endl;
}
};
int main()
{
B b;
b.print();
return 0;
}
Then we just have to run these commands:
g++ -S main.cpp #create the listing for the friendless main.cpp
mv main.s main_no.s #rename it so we don't lose it
sed -ie 's/\/\/ friend class A;/ friend class A;/g' main.cpp
g++ -S main.cpp #replace the line so we now have a friend
diff main.s main_no.s
And as we can see by the empty output of diff , both files are exactly the same. As said in the comments of the question, compilers are free to encode any information the way they want so even though this test passes today, GCC could decide to include friend relationships in the .s files in the future, making this simplistic test fail.
In that case, you'd need to remove any information put by gcc in the .s file that's not actually instructions (they usually start with a dot in the file)
Related
I was recently having some "undefined reference" errors that I managed to resolve but I don't understand why the solution works. I have the following main source file:
Main.cpp:
#include <iostream>
#include "Log.h"
int main()
{
std::cout << "Hello World!" << std::endl;
Log log;
log.SetLevel(Log::LevelWarning);
log.Error("Hello!");
log.Warning("Hello!");
log.Info("Hello!");
std::cin.get();
}
which references a class declared in a separate source file:
Log.cpp:
#include <iostream>
class Log
{
public:
enum Level
{
LevelError, LevelWarning, LevelInfo
};
private:
Level m_LogLevel = LevelInfo;
public:
void SetLevel (Level level)
{
m_LogLevel = level;
}
void Error (const char* message)
{
if (m_LogLevel >= LevelError)
std::cout << "[ERROR]: " << message << std::endl;
}
void Warning (const char* message)
{
if (m_LogLevel >= LevelWarning)
std::cout << "[WARNING]: " << message << std::endl;
}
void Info (const char* message)
{
if (m_LogLevel >= LevelInfo)
std::cout << "[INFO]: " << message << std::endl;
}
};
Log.h:
#pragma once
class Log
{
public:
enum Level { LevelError, LevelWarning, LevelInfo };
private:
Level m_LogLevel;
public:
void SetLevel (Level);
void Error (const char*);
void Warning (const char*);
void Info (const char*);
};
The code above gives me the linker errors "undefined reference to Log::..." for all members of the class Log being called in Main.cpp. Searching around I eventually found comment saying something along the lines of "static members and functions should be initialized", which gave me the idea of adding the following:
void Init()
{
Log log;
log.SetLevel(Log::LevelInfo);
log.Error("NULL");
log.Warning("NULL");
log.Info("NULL");
}
To my Log.cpp file. This amazingly solves the issue and the project builds successfully, but these members are not declared as static and so I don't understand why this works, or even if this is the correct solution.
I'm using gcc in linux and compiling with "g++ Main.cpp Log.cpp -o main". Source files are in the same folder.
c++ is not java or c#. This construct won't generate any code at all:
class X
{
public:
void foo()
{
std::cout << "Hello, world"<< std::endl;
}
};
Yes, in java after compiling that you will get X.class which you can use. However in c++ this does not produce anything.
proof:
#include <stdio.h>
class X
{
void foo()
{
printf("X");
}
};
$ gcc -S main.cpp
$ cat main.s
.file "main.cpp"
.ident "GCC: (GNU) 4.9.3"
.section .note.GNU-stack,"",#progbits
In c++ you need something other than "definitions" for anything to be compiled.
If you want to emulate java-like compiler behaviour do this:
class X
{
public:
void foo();
};
void X::foo()
{
std::cout << "Hello, world"<< std::endl;
}
this will generate object file containing void X::foo().
proof:
$ gcc -c test.cpp
$ nm --demangle test.o
0000000000000000 T X::foo()
Another option is of course use inline method as you do but in this case you would need to #include whole "Log.cpp" into your "Main.cpp".
In c++ compilation is done by "translation units" instead of classes. One unit (say .cpp) produces one object file (.o). Such object file contains machine instructions and data.
Compiler does not see anything outside of a translation unit being compiled now.
Thereofre, unlike Java when main.cpp is compiled compiler only sees what is #included into main.cpp and main.cpp itself. Hence the compiler do not see the contents of Log.cpp at this time.
It's only at link time object files generated from translation units are merged together. But at this time it's too late to compile anything.
A class with inline function (like the first example) does not define any machine instructions or data.
For inline members of class machine instructions will be generated only when you use them.
Since you use your class members in main.cpp which is outside of translation unit Log.cpp during compilation of Log.cpp compiler does not generate any machine instructions for them.
Problem of One Definition Rule is a different one.
Your code is not correctly organized. You should not have two different class Log { ... }; contents for the same class.
Main.cpp needs to know the contents of class Log, so the (single) definition of class Log will need to be in your header file. That leaves the question of the definitions of the class member functions. There are three ways to define a class member function:
Inside the class definition (which is in a header).
This is what you attempted in your Log.cpp file. If you define all the members in the class definition in Log.h, then you don't need a Log.cpp file at all.
Outside the class definition, with the inline keyword, in the header file.
This would look like:
// Log.h
class Log
{
// ...
public:
void SetLevel(Level level);
// ...
};
inline void Log::SetLevel(Level level)
{
m_LogLevel = level;
}
Outside the class definition, with no inline keyword, in the source file.
This would look like:
// Log.h
class Log
{
// ...
public:
void SetLevel(Level level);
// ...
};
// Log.cpp
#include "Log.h"
void Log::SetLevel(Level level)
{
m_LogLevel = level;
}
Note Log.cpp includes Log.h, so that the compiler sees the class definition before you start trying to define its members.
You are allowed to mix and match these. Although there are no strict rules on what is best, a general guideline is that small and simple functions can go in the header file, and large and complex functions might do better in the source file. Some programmers recommend not putting any function definitions inside the class definition at all, or limiting this option to cases where the definition is very short and helps make clear what the purpose of the function is, since then the (public part of the) class definition is a summary of what the class does, not details about how it does it.
In some cases, it might be appropriate to define a class inside a source *.cpp file - but this means it can only be used from that file.
I apologize if the title is not fully self-explanatory. I'm trying to understand why my singleton factory pattern is not working properly, and I ran into a bizarre difference when using library vs linking single objects files.
Here's a simplified version of the code:
main.cpp
#include <iostream>
#include "bar.hpp"
int main (int /*argc*/, char** /*argv*/)
{
A::get().print();
return 0;
}
bar.hpp
#ifndef BAR_HPP
#define BAR_HPP
#include <iostream>
class A
{
public:
static A& get ()
{
static A a;
return a;
}
bool set(const int i)
{
m_i = i;
print();
return true;
}
void print ()
{
std::cout << "print: " << m_i << "\n";
}
private:
int m_i;
A () : m_i(0) {}
};
#endif // BAR_HPP
baz.hpp
#ifndef BAZ_HPP
#define BAZ_HPP
#include "bar.hpp"
namespace
{
static bool check = A::get().set(2);
}
#endif // BAZ_HPP
baz.cpp
#include "baz.hpp"
Now, I build my "project" in two ways:
Makefile:
all:
g++ -std=c++11 -c baz.cpp
g++ -std=c++11 -o test main.cpp baz.o
lib:
g++ -std=c++11 -c baz.cpp
ar rvs mylib.a baz.o
g++ -std=c++11 -o test main.cpp mylib.a
Here are the outputs I get:
$ make all
$ ./test
print: 2
print: 2
$ make lib
$ ./test
print: 0
In the first case the call to A::get().set(2) in baz.hpp takes place, and the same instantiation of A is then used in the main function, which therefore prints 2. In the second case, the call to A::get().set(2) in baz.hpp never takes place, and in the main function the value set by the constructor (that is, 0) is printed.
So finally I can ask my question: why is the behavior different in the two cases? I would expect that either both print 0 once or print 2 twice. I always assumed that a library was just a compact way to ship object files, and that the behavior of linking mylib.a should be the same as that of linking baz.o directly. Why isn't that the case?
Edit: the reason, as explained by Richard, is that no symbols defined in baz.cpp are required in main.cpp, so baz.o is not extracted from the library and linked. This raises another question: is there a workaround to ensure that the instruction A::get().set(2) is executed? I would like to avoid making the singleton a global object, but I'm not sure it's possible. I would also like to avoid to include baz.hpp in the main, since there may be many bazxyz.hpp and that would require main.cpp to know in advance all of them, defying the whole purpose of the factory-like registration process...
If this is to be a static library, then some module somewhere is going to have to address something in each implementation file of the objects that are going to register themselves with the factory.
A reasonable place for this would be in bar.cpp (which is a file you don't yet have). It would contain some or all of the implementation of A plus some means of calling the registration functions the widgets you're going to create.
Self-discovery only works if the object files are linked into the executable. This gives the c++ startup sequence a chance to know about and construct all objects with global linkage.
D has a fantastic module system which reduces compilation times dramatically compared to C++. According to the documentation D still provides opaque structs and unions in order to enable the pimpl idiom. My question is: How can I declare a nested struct (or union) in one module and define it in another one? What is the syntax for that?
In C++ the header would look like this
struct S {
...
struct Impl;
Impl * p;
};
and the implementation file (cpp-file) would use some interesting-looking ::-syntax like this:
#include "header.h"
struct S::Impl {
...
};
How do I implement the same in D?
D (DMD, at least) uses .di files for declarations. They are somewhat equivalent to C .h files, however they are optional. The D compiler can generate .di files automatically (when the -H switch is specified), although I believe that currently all it does is strip function bodies and unittests.
Here's one way to achieve PImpl using .di files:
mod.di:
struct S
{
struct I;
I* pi;
}
mod.d:
struct S
{
struct I
{
int v;
}
I* pi;
}
Note that it is currently your responsibility to make sure that the fields in S are the same in both the .d and .di file - if they differ, the compiled modules will have differing knowledge of how the fields are laid out, which can lead to memory corruption. The current compiler implementations do not verify if definitions match in .d and .di files.
My question is: How can I declare a nested struct (or union) in one module and define it in another one?
To get it straight - it is intentionally impossible in D by design. It is a direct consequence of having a reliable module system - every symbol declaration is implicitly qualified by a module name it is declared inside. And for variety of reasons you can't hijack a symbol into another modules "namespace".
That said, it is not necessary to do it in same module to use pimpl approach. You can refer to CyberShadow answer for more details.
Another approach is based on the D's system of class's hierarchy:
all objects inherits explicitly or implicitly the Object.
So the idea is to implement OuterClass with pimpl, generate corresponding
di-file, manually remove all definitions of OuterClassPrivate from di-file
and change declaration of the pimpl-member.
For example:
first version of the shared library
module pimpl.mylib;
class PimplTest
{
this()
{
mImpl = new PimplTestPrivate();
}
~this()
{
}
string sayWhat(string what)
{
return mImpl.ku ~ " " ~ what;
}
private class PimplTestPrivate
{
string ku = "Ku!!1";
}
private PimplTestPrivate mImpl;
}
test application:
module main;
import std.stdio;
import pimpl.mylib;
void main()
{
PimplTest t = new PimplTest();
writeln(t.sayWhat("?"));
}
Shared mylib may be built the following way (under Linux):
$ dmd -H -c mylib.d -fPIC
$ dmd -ofmylib.so mylib.o -shared -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/phobos/library/is
Then edit genereated di-file:
// D import file generated from 'mylib.d'
module pimpl.mylib;
class PimplTest
{
this();
~this();
string sayWhat(string what);
// NOTE this
private Object mImpl;
}
Compile the test itsel
$ dmd -c main.d /path/to/first/version/of/mylib.di
$ ln -s /path/to/first/version/of/mylib.so .
$ dmd main.o -L-l:mylib.so -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/phobos/library/is:.
$ ./main
Say: ?
Then we change mylib:
module pimpl.mylib;
import std.conv;
class PimplTest
{
this()
{
mImpl = new PimplTestPrivate();
}
~this()
{
}
string sayWhat(string what)
{
return mImpl.getMessage1(mImpl.getValue(), what);
}
private class PimplTestPrivate
{
int getValue()
{
return 42;
}
string ku = "Ku!!1";
string getMessage1(int x, string y)
{
return "x = " ~ to!(string)(x) ~ ", " ~ y;
}
double pi = 22.0/7.0;
}
private PimplTestPrivate mImpl;
}
Compile it and replace binary shared object (so file) of the first version of mylib with just built one. Running test application must not crash but the output will be different.
how to prove that when that compile the templates in C++, the compiler generates an instantiation in each compilation unit that uses it, then the linker throws away all but one of them[the commond model];
so there are 2 thing we should prove
1. create multiple copies 2.remove the copies when link
we can prove the second one use the code like
////head.h
#ifndef _TEMP_H
#define _TEMP_H
#include <typeinfo>
#include <iostream>
template<typename T>
class Test
{
public:
Test(T i = 0) : val(i) {}
void getId() const
{
std::cout << typeid(*this).name() << std::endl;
}
void getVal() const
{
std::cout << "Val: " << val << std::endl;
}
private:
T val;
};
#endif
//a.cpp
#include "head.h"
Test<int> a(1);
//b.cpp
#include "head.h"
extern Test<int> a;
int main()
{
Test<int> b;
a.getId();
b.getId();
a.getVal();
b.getVal();
return 0;
}
compiler: g++ 4.4.1
get the result :
4TestIiE
4TestIiE
Val: 1
Val: 0
So the second one has been proved;
But I can not prove the first one
I google it and have some sugestions as followed
1. use the dump yes we can dump the objfile and get the result
but can we write some code to output something to prove it??
Number 1 is easy. Just create a bunch of different source files and include the template header in each one, and use the template class to produce some output. Then compile each source file separately. Now link them each one by one with a main program that calls it. If you don't get any linker errors but the program generates the output, that proves each compiled object file contained the template code.
P.S. The extra copies might not get eliminated, they may still exist as dead code in the executable.
Some compilers definitely don't do that. The IBM C++ compiler generates required templates at link time and compiles them then, in a repeat-until-closure process.
In the new Go language, how do I call C++ code? In other words, how can I wrap my C++ classes and use them in Go?
Update: I've succeeded in linking a small test C++ class with Go
If you wrap you C++ code with a C interface you should be able to call your library with cgo (see the example of gmp in $GOROOT/misc/cgo/gmp).
I'm not sure if the idea of a class in C++ is really expressible in Go, as it doesn't have inheritance.
Here's an example:
I have a C++ class defined as:
// foo.hpp
class cxxFoo {
public:
int a;
cxxFoo(int _a):a(_a){};
~cxxFoo(){};
void Bar();
};
// foo.cpp
#include <iostream>
#include "foo.hpp"
void
cxxFoo::Bar(void){
std::cout<<this->a<<std::endl;
}
which I want to use in Go. I'll use the C interface
// foo.h
#ifdef __cplusplus
extern "C" {
#endif
typedef void* Foo;
Foo FooInit(void);
void FooFree(Foo);
void FooBar(Foo);
#ifdef __cplusplus
}
#endif
(I use a void* instead of a C struct so the compiler knows the size of Foo)
The implementation is:
//cfoo.cpp
#include "foo.hpp"
#include "foo.h"
Foo FooInit()
{
cxxFoo * ret = new cxxFoo(1);
return (void*)ret;
}
void FooFree(Foo f)
{
cxxFoo * foo = (cxxFoo*)f;
delete foo;
}
void FooBar(Foo f)
{
cxxFoo * foo = (cxxFoo*)f;
foo->Bar();
}
with all that done, the Go file is:
// foo.go
package foo
// #include "foo.h"
import "C"
import "unsafe"
type GoFoo struct {
foo C.Foo;
}
func New()(GoFoo){
var ret GoFoo;
ret.foo = C.FooInit();
return ret;
}
func (f GoFoo)Free(){
C.FooFree(unsafe.Pointer(f.foo));
}
func (f GoFoo)Bar(){
C.FooBar(unsafe.Pointer(f.foo));
}
The makefile I used to compile this was:
// makefile
TARG=foo
CGOFILES=foo.go
include $(GOROOT)/src/Make.$(GOARCH)
include $(GOROOT)/src/Make.pkg
foo.o:foo.cpp
g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $# -c $(CGO_CFLAGS) $<
cfoo.o:cfoo.cpp
g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $# -c $(CGO_CFLAGS) $<
CGO_LDFLAGS+=-lstdc++
$(elem)_foo.so: foo.cgo4.o foo.o cfoo.o
gcc $(_CGO_CFLAGS_$(GOARCH)) $(_CGO_LDFLAGS_$(GOOS)) -o $# $^ $(CGO_LDFLAGS)
Try testing it with:
// foo_test.go
package foo
import "testing"
func TestFoo(t *testing.T){
foo := New();
foo.Bar();
foo.Free();
}
You'll need to install the shared library with make install, then run make test. Expected output is:
gotest
rm -f _test/foo.a _gotest_.6
6g -o _gotest_.6 foo.cgo1.go foo.cgo2.go foo_test.go
rm -f _test/foo.a
gopack grc _test/foo.a _gotest_.6 foo.cgo3.6
1
PASS
Seems that currently SWIG is best solution for this:
https://www.swig.org/Doc4.0/Go.html
It supports inheritance and even allows to subclass C++ class with Go struct so when overridden methods are called in C++ code, Go code is fired.
Section about C++ in Go FAQ is updated and now mentions SWIG and no longer says "because Go is garbage-collected it will be unwise to do so, at least naively".
As of go1.2+, cgo automatically incorporates and compiles C++ code:
http://golang.org/doc/go1.2#cgo_and_cpp
You can't quite yet from what I read in the FAQ:
Do Go programs link with C/C++ programs?
There are two Go compiler implementations, gc (the 6g program and friends) and gccgo. Gc uses a different calling convention and linker and can therefore only be linked with C programs using the same convention. There is such a C compiler but no C++ compiler. Gccgo is a GCC front-end that can, with care, be linked with GCC-compiled C or C++ programs.
The cgo program provides the mechanism for a “foreign function interface” to allow safe calling of C libraries from Go code. SWIG extends this capability to C++ libraries.
I've created the following example based on Scott Wales' answer. I've tested it in macOS High Sierra 10.13.3 running go version go1.10 darwin/amd64.
(1) Code for library.hpp, the C++ API we aim to call.
#pragma once
class Foo {
public:
Foo(int value);
~Foo();
int value() const;
private:
int m_value;
};
(2) Code for library.cpp, the C++ implementation.
#include "library.hpp"
#include <iostream>
Foo::Foo(int value) : m_value(value) {
std::cout << "[c++] Foo::Foo(" << m_value << ")" << std::endl;
}
Foo::~Foo() { std::cout << "[c++] Foo::~Foo(" << m_value << ")" << std::endl; }
int Foo::value() const {
std::cout << "[c++] Foo::value() is " << m_value << std::endl;
return m_value;
}
(3) Code for library-bridge.h the bridge needed to expose a C API implemented in C++ so that go can use it.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void* LIB_NewFoo(int value);
void LIB_DestroyFoo(void* foo);
int LIB_FooValue(void* foo);
#ifdef __cplusplus
} // extern "C"
#endif
(4) Code for library-bridge.cpp, the implementation of the bridge.
#include <iostream>
#include "library-bridge.h"
#include "library.hpp"
void* LIB_NewFoo(int value) {
std::cout << "[c++ bridge] LIB_NewFoo(" << value << ")" << std::endl;
auto foo = new Foo(value);
std::cout << "[c++ bridge] LIB_NewFoo(" << value << ") will return pointer "
<< foo << std::endl;
return foo;
}
// Utility function local to the bridge's implementation
Foo* AsFoo(void* foo) { return reinterpret_cast<Foo*>(foo); }
void LIB_DestroyFoo(void* foo) {
std::cout << "[c++ bridge] LIB_DestroyFoo(" << foo << ")" << std::endl;
AsFoo(foo)->~Foo();
}
int LIB_FooValue(void* foo) {
std::cout << "[c++ bridge] LIB_FooValue(" << foo << ")" << std::endl;
return AsFoo(foo)->value();
}
(5) Finally, library.go, the go program calling the C++ API.
package main
// #cgo LDFLAGS: -L. -llibrary
// #include "library-bridge.h"
import "C"
import "unsafe"
import "fmt"
type Foo struct {
ptr unsafe.Pointer
}
func NewFoo(value int) Foo {
var foo Foo
foo.ptr = C.LIB_NewFoo(C.int(value))
return foo
}
func (foo Foo) Free() {
C.LIB_DestroyFoo(foo.ptr)
}
func (foo Foo) value() int {
return int(C.LIB_FooValue(foo.ptr))
}
func main() {
foo := NewFoo(42)
defer foo.Free() // The Go analog to C++'s RAII
fmt.Println("[go]", foo.value())
}
Using the following Makefile
liblibrary.so: library.cpp library-bridge.cpp
clang++ -o liblibrary.so library.cpp library-bridge.cpp \
-std=c++17 -O3 -Wall -Wextra -fPIC -shared
I can run the example program as follows:
$ make
clang++ -o liblibrary.so library.cpp library-bridge.cpp \
-std=c++17 -O3 -Wall -Wextra -fPIC -shared
$ go run library.go
[c++ bridge] LIB_NewFoo(42)
[c++] Foo::Foo(42)
[c++ bridge] LIB_NewFoo(42) will return pointer 0x42002e0
[c++ bridge] LIB_FooValue(0x42002e0)
[c++] Foo::value() is 42
[go] 42
[c++ bridge] LIB_DestroyFoo(0x42002e0)
[c++] Foo::~Foo(42)
Important
The comments above import "C" in the go program are NOT OPTIONAL. You must put them exactly as shown so that cgo knows which header and library to load, in this case:
// #cgo LDFLAGS: -L. -llibrary
// #include "library-bridge.h"
import "C"
Link to GitHub repo with the full example.
Looks it's one of the early asked question about Golang . And same time answers to never update . During these three to four years , too many new libraries and blog post has been out . Below are the few links what I felt useful .
SWIG and Go
Calling C++ Code From Go With SWIG
On comparing languages, C++ and Go
GoForCPPProgrammers
There's talk about interoperability between C and Go when using the gcc Go compiler, gccgo. There are limitations both to the interoperability and the implemented feature set of Go when using gccgo, however (e.g., limited goroutines, no garbage collection).
You're walking on uncharted territory here. Here is the Go example for calling C code, perhaps you can do something like that after reading up on C++ name mangling and calling conventions, and lots of trial and error.
If you still feel like trying it, good luck.
You might need to add -lc++ to the LDFlags for Golang/CGo to recognize the need for the standard library.
The problem here is that a compliant implementation does not need to put your classes in a compile .cpp file. If the compiler can optimize out the existence of a class, so long as the program behaves the same way without it, then it can be omitted from the output executable.
C has a standardized binary interface. Therefore you'll be able to know that your functions are exported. But C++ has no such standard behind it.
Funny how many broader issues this announcement has dredged up. Dan Lyke had a very entertaining and thoughtful discussion on his website, Flutterby, about developing Interprocess Standards as a way of bootstrapping new languages (and other ramifications, but that's the one that is germane here).
This can be achieved using command cgo.
In essence
'If the import of "C" is immediately preceded by a comment, that comment, called the preamble, is used as a header when compiling the C parts of the package. For example:'
source:https://golang.org/cmd/cgo/
// #include <stdio.h>
// #include <errno.h>
import "C"