How to expose derived class function in boost python - c++

I would like to implement the expose module in derived class (.h or .cpp file). its work fine, when I exposed this in main in one BOOST_PYTHON_MODULE but when I exposed differently in abstract and derived class its get error one or more multiply defined symbols errors. the example code is as follows.
**Base.h**
class Base
{
public:
virtual void Set(const std::vector<std::string>& AllParameters) = 0;
};
struct BaseWrap : Base, wrapper<Base>
{
void Set(const std::vector<std::string>& AllParameters)
{
this->get_override("Set")(AllParameters);
}
**Base.cpp**
BOOST_PYTHON_MODULE(Example)
{
class_<Basewrapper , boost::noncopyable> ("Base")
.def("Set",pure_virtual(&Base::Set))
;
}
**Derived.h**
class Derived : public Base
{
public:
int test(int a, int b);
};
BOOST_PYTHON_MODULE(Example)
{
class_<Derived , boost::noncopyable> ("Derived")
.def("test",&Derived ::test)
;
}
**Derived.cpp**
void Derived:: test(int a , int b)
{
return a+b;
}

The BOOST_PYTHON_MODULE macro defines a function with identifiers based on the provided argument. Hence, defining the Example module in both Base.cpp and Derived.h violates the one definition rule when linking them into the same library. To resolve this, consider splitting the function bodies that export each individual class into their own functions (i.e. export_base() and export_derived()), and have a single file (example.cpp) that defines BOOST_PYTHON_MODULE with a body that invokes the other export functions. This technique can be seen here.

Related

can't find overloaded method from inherited class template

This is the first time I am using class templates so please don't be to harsh if I made a simply mistake.
I have a class template class A<class T>. It has a method init() that is pure virtual and therefore will be implemented separately in every derived class. What all these possible derived classes will have in common is an init(T* i_x) which basically does some general stuff and then calls the init(). Because this will be the same for every derived class I want to define it in the base class template already. But somehow my compiler doesn't find the right function.
If I try to use the init(T* i_x) on an object of a derived class A_der I get the error:
no matching function for call to 'A_der::init(B_der*)
The classes used for the template parameter T will all be derived from another class B. Therefore the error message involves the class B_der which is derived from class B.
I boiled the problem down to a small example, which should involve everything that is important for the problem. If I try to compile this example in Visual Studio (normally I work in STM32CubeIDE) I get the following error
Severity Code Description Project File Line Suppression State
Error C2660 'A_der::init': function does not take 1
arguments template_class-overload_inherited_method [...]\main.cpp 8
So somehow the only function the compiler finds at this point is init() but not the base class template method init(T* ).
Can somebody please tell me why it is like that and what can I do to get the behaviour I want (without implementing a similar init(T* ) in every derived class of A?
Here is my example code:
base class template A - declaration - A.hpp
template<class T>
class A
{
protected:
T* m_x;
public:
virtual void connect(T* i_x) final;
virtual void init() = 0;
virtual void init(T* i_x) final;
};
base class template A - implementation - A.cpp
#include "A.hpp"
template<class T>
void A<T>::connect(T* i_x)
{
//some checks
m_x = i_x; //connects object of B to A
}
template<class T>
void A<T>::init(T* i_x)
{
connect(i_x);
init();
}
derived class A_der
#include "A.hpp"
#include "B_der.hpp"
#pragma once
class A_der : public A<B_der>
{
void init() override;
};
void A_der::init()
{
//Initialization which needs a B_der connected already
}
main.cpp
#include "B_der.hpp"
#include "A_der.hpp"
int main(void)
{
B_der testB;
A_der testA;
testA.init(&testB);
return 0;
}
For the sake of completeness:
class B
{
};
class B_der : public B
{
};
EDIT - Solved
Thanks a lot for the fast replies.
The combination of the comments from #BoP and #Jarod42 solved the problem.
I had to unhide the method with using A<B_der>::init (actually renaming might be the more elegant way) and move the implementation of A into A.hpp.
I will offer the updated example which builds successfully with Visual Studio 2019 for me here:
base class A
template<class T>
class A
{
protected:
T* m_x;
public:
virtual void connect(T* i_x) final;
virtual void init() = 0;
virtual void init(T* i_x) final;
};
template<class T>
void A<T>::connect(T* i_x)
{
//some checks
m_x = i_x; //connects object of B to A
}
template<class T>
void A<T>::init(T* i_x)
{
connect(i_x);
init();
}
derivad class A_der
A_der.hpp
#include "A.hpp"
#include "B_der.hpp"
class A_der : public A<B_der>
{
public:
void init() override;
using A<B_der>::init;
};
A_der.cpp
#include "A_der.hpp"
void A_der::init()
{
//Initialization which needs a B_der connected already
}
main.cpp
#include "B_der.hpp"
#include "A_der.hpp"
int main(void)
{
B_der testB;
A_der testA;
testA.init(&testB);
return 0;
}
for completeness
B.hpp
class B
{
};
B_der.hpp
#include "B.hpp"
class B_der : public B
{
};
I also forgot to make the methods of A_der public in the earlier example, this is corrected here. And I removed the #pragma onces in this example.
class A_der : public A<B_der>
{
void init() override;
};
When you declare a function init in the derived class, it hides all things named init from the base class. This is just like when declaring something in an inner scope - it hides things with the same name from outer scopes.
There are ways to import the hidden names, but an easy solution would be to just chose a different name, like init_base. Or, probably better, pass a parameter to the class constructor.

Google-Mock an already declared method

The syntax of MOCK_METHOD can be used inside a class definition:
class A {
MOCK_METHOD0(f, void(void));
};
Is it possible to mock a method that has already been declared? What I want is to do something similar to:
#include "gmock/gmock.h"
class HelloTest {
void f();
};
MOCK_METHOD0(HelloTest::f, void(void));
The idea is to put the class definition in an hpp file and then the mocks in a cpp file. In effect, my class definition with its methods' prototypes needs to be in common with other cpp files in my build chain and I don't want to use virtual functions.
Unfortunately, when I try to do what I wrote above, I get the following error on the line that contains MOCK_METHOD0:
error: ‘gmock0_HelloTest’ has not been declared
What does this error mean and is there a way to do what I want?
To begin with, your MOCK_METHOD0() declaration must belong to a mock class, under a public section. For instance, your code snippet:
#include "gmock/gmock.h"
class HelloTest {
void f();
};
MOCK_METHOD0(HelloTest::f, void(void));
Should instead look like this:
#include "gmock/gmock.h"
class HelloTest {
virtual void f();
};
class Mock_HelloTest : public HelloTest {
public:
MOCK_METHOD0(f, void(void));
};
Now, you'll notice that I've changed f() to be virtual instead, since your use of HelloTest::f in MOCK_METHOD0 requires f() to be virtual.
Since you don't want to use virtual functions, your only other option is to use what the Google Mock team calls hi-perf dependency injection. With this non-virtual approach, you'd have to create a separate mock class that doesn't inherit from HelloTest. You'd also need to templatize any code that currently uses HelloTest to switch between HelloTest in production and Mock_HelloTest in tests.
As an example, let's say you have the following function that calls HelloTest::f():
void RunHelloTest() {
HelloTest HT;
HT.f();
}
You would set up your code snippet as follows:
#include "gmock/gmock.h"
class HelloTest {
void f(); // <- f is no longer virtual
};
class Mock_HelloTest { // <- Mock_HelloTest no longer inherits from HelloTest
public:
MOCK_METHOD0(f, void(void));
};
And modify RunHelloTest() to accept a template type argument:
template <class HelloTestClass>
void RunHelloTest() {
HelloTestClass HT;
HT.f(); // <- will call HelloTest::f() or Mock_HelloTest::f()
}
With this setup, you'd call RunHelloTest<HelloTest>() in your production code, and RunHelloTest<Mock_HelloTest>() in your test code.

Standard way to control symbol visibility

Using C and plain functions in C++, I can prevent the functions' symbols to be exported by using static keyword:
static int foo(int a, int b) { /* ... */ }
But in a class, defining a function as static has a completely different meaning. Is there a way to ensure the compiler that my whole class will be used only within module, and there is no need to export any of its methods' symbols?
Use an anonymous namespace.
namespace
{
class C
{
C() {}
void f() {}
};
void f();
}
class ExportedClass
{
ExportedClass() {}
void f() {}
};
void exportedFunction() {}
As you can see, you should do this for normal functions, too. The usage of static for this is discouraged.
You can use the anonymous namespace. For example,
// file foo.cc
namespace {
int symbol1 = 0;
struct auxiliary { /* ... */ } symbol2;
}
void foo(int x)
{
// uses symbol1 and symbol2
}
when symbol1 and symbol2 are not 'visible'.
Depending on what you want and why you are doing it you could move the class into the .cpp file. This works for example if you are implementing a library. Have a look at the discussion at Putting class declaration in .cpp file
To be more specific your class should go in it's own separate translation unit away from main and away from classes outside of your module.

How to fake "visibility of class" (not of functions) in C++?

There is no feature that control visibility/accessibility of class in C++.
Is there any way to fake it?
Are there any macro/template/magic of C++ that can simulate the closest behavior?
Here is the situation
Util.h (library)
class Util{
//note: by design, this Util is useful only for B and C
//Other classes should not even see "Util"
public: static void calculate(); //implementation in Util.cpp
};
B.h (library)
#include "Util.h"
class B{ /* ... complex thing */ };
C.h (library)
#include "Util.h"
class C{ /* ... complex thing */ };
D.h (user)
#include "B.h" //<--- Purpose of #include is to access "B", but not "Util"
class D{
public: static void a(){
Util::calculate(); //<--- should compile error
//When ctrl+space, I should not see "Util" as a choice.
}
};
My poor solution
Make all member of Util to be private, then declare :-
friend class B;
friend class C;
(Edit: Thank A.S.H for "no forward declaration needed here".)
Disadvantage :-
It is a modifying Util to somehow recognize B and C.
It doesn't make sense in my opinion.
Now B and C can access every member of Util, break any private access guard.
There is a way to enable friend for only some members but it is not so cute, and unusable for this case.
D just can't use Util, but can still see it.
Util is still a choice when use auto-complete (e.g. ctrl+space) in D.h.
(Edit) Note: It is all about convenience for coding; to prevent some bug or bad usage / better auto-completion / better encapsulation. This is not about anti-hacking, or prevent unauthorized access to the function.
(Edit, accepted):
Sadly, I can accept only one solution, so I subjectively picked the one that requires less work and provide much flexibility.
To future readers, Preet Kukreti (& texasbruce in comment) and Shmuel H. (& A.S.H is comment) has also provided good solutions that worth reading.
I think that the best way is not to include Util.h in a public header at all.
To do that, #include "Util.h" only in the implementation cpp file:
Lib.cpp:
#include "Util.h"
void A::publicFunction()
{
Util::calculate();
}
By doing that, you make sure that changing Util.h would make a difference only in your library files and not in the library's users.
The problem with this approach is that would not be able to use Util in your public headers (A.h, B.h). forward-declaration might be a partial solution for this problem:
// Forward declare Util:
class Util;
class A {
private:
// OK;
Util *mUtil;
// ill-formed: Util is an incomplete type
Util mUtil;
}
One possible solution would be to shove Util into a namespace, and typedef it inside the B and C classes:
namespace util_namespace {
class Util{
public:
static void calculate(); //implementation in Util.cpp
};
};
class B {
typedef util_namespace::Util Util;
public:
void foo()
{
Util::calculate(); // Works
}
};
class C {
typedef util_namespace::Util Util;
public:
void foo()
{
Util::calculate(); // Works
}
};
class D {
public:
void foo()
{
Util::calculate(); // This will fail.
}
};
If the Util class is implemented in util.cpp, this would require wrapping it inside a namespace util_namespace { ... }. As far as B and C are concerned, their implementation can refer to a class named Util, and nobody would be the wiser. Without the enabling typedef, D will not find a class by that name.
One way to do this is by friending a single intermediary class whose sole purpose is to provide an access interface to the underlying functionality. This requires a bit of boilerplate. Then A and B are subclasses and hence are able to use the access interface, but not anything directly in Utils:
class Util
{
private:
// private everything.
static int utilFunc1(int arg) { return arg + 1; }
static int utilFunc2(int arg) { return arg + 2; }
friend class UtilAccess;
};
class UtilAccess
{
protected:
int doUtilFunc1(int arg) { return Util::utilFunc1(arg); }
int doUtilFunc2(int arg) { return Util::utilFunc2(arg); }
};
class A : private UtilAccess
{
public:
int doA(int arg) { return doUtilFunc1(arg); }
};
class B : private UtilAccess
{
public:
int doB(int arg) { return doUtilFunc2(arg); }
};
int main()
{
A a;
const int x = a.doA(0); // 1
B b;
const int y = b.doB(0); // 2
return 0;
}
Neither A or B have access to Util directly. Client code cannot call UtilAccess members via A or B instances either. Adding an extra class C that uses the current Util functionality will not require modification to the Util or UtilAccess code.
It means that you have tighter control of Util (especially if it is stateful), keeping the code easier to reason about since all access is via a prescribed interface, instead of giving direct/accidental access to anonymous code (e.g. A and B).
This requires boilerplate and doesn't automatically propagate changes from Util, however it is a safer pattern than direct friendship.
If you do not want to have to subclass, and you are happy to have UtilAccess change for every using class, you could make the following modifications:
class UtilAccess
{
protected:
static int doUtilFunc1(int arg) { return Util::utilFunc1(arg); }
static int doUtilFunc2(int arg) { return Util::utilFunc2(arg); }
friend class A;
friend class B;
};
class A
{
public:
int doA(int arg) { return UtilAccess::doUtilFunc1(arg); }
};
class B
{
public:
int doB(int arg) { return UtilAccess::doUtilFunc2(arg); }
};
There are also some related solutions (for tighter access control to parts of a class), one called Attorney-Client and the other called PassKey, both are discussed in this answer: clean C++ granular friend equivalent? (Answer: Attorney-Client Idiom) . In retrospect, I think the solution I have presented is a variation of the Attorney-Client idiom.

C++ Calling a function from another class

Very new to c++ having trouble calling a function from another class.
Class B inherits from Class A, and I want class A to be able to call a function created in class B.
using namespace std;
class B;
class A
{
public:
void CallFunction ()
{
B b;
b.bFunction();
}
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
It all looks fine on screen (no obvious errors) but when I try to compile it i get an error C2079 'b' uses undefined class B.
I've tried making them pointers/ friends but I'm getting the same error.
void CallFunction ()
{ // <----- At this point the compiler knows
// nothing about the members of B.
B b;
b.bFunction();
}
This happens for the same reason that functions in C cannot call each other without at least one of them being declared as a function prototype.
To fix this issue we need to make sure both classes are declared before they are used. We separate the declaration from the definition. This MSDN article explains in more detail about the declarations and definitions.
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{ ... }
};
void A::CallFunction ()
{
B b;
b.bFunction();
}
What you should do, is put CallFunction into *.cpp file, where you include B.h.
After edit, files will look like:
B.h:
#pragma once //or other specific to compiler...
using namespace std;
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
B.cpp
#include "B.h"
void A::CallFunction(){
//use B object here...
}
Referencing to your explanation, that you have tried to change B b; into pointer- it would be okay, if you wouldn't use it in that same place. You can use pointer of undefined class(but declared), because ALL pointers have fixed byte size(4), so compiler doesn't have problems with that. But it knows nothing about the object they are pointing to(simply: knows the size/boundary, not the content).
So as long as you are using the knowledge, that all pointers are same size, you can use them anywhere. But if you want to use the object, they are pointing to, the class of this object must be already defined and known by compiler.
And last clarification: objects may differ in size, unlike pointers. Pointer is a number/index, which indicates the place in RAM, where something is stored(for example index: 0xf6a7b1).
class B is only declared but not defined at the beginning, which is what the compiler complains about. The root cause is that in class A's Call Function, you are referencing instance b of type B, which is incomplete and undefined. You can modify source like this without introducing new file(just for sake of simplicity, not recommended in practice):
using namespace std;
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
// postpone definition of CallFunction here
void A::CallFunction ()
{
B b;
b.bFunction();
}
in A you have used a definition of B which is not given until then , that's why the compiler is giving error .
Forward declare class B and swap order of A and B definitions: 1st B and 2nd A. You can not call methods of forward declared B class.
Here's my solution to the issue. Tried to keep it straight and simple.
#include <iostream>
using namespace std;
class Game{
public:
void init(){
cout << "Hi" << endl;
}
}g;
class b : Game{ //class b uses/imports class Game
public:
void h(){
init(); //Use function from class Game
}
}A;
int main()
{
A.h();
return 0;
}
You can also have a look at the curiously recurring template pattern and solve your problem similar to this:
template<typename B_TYPE>
struct A
{
int callFctn()
{
B_TYPE b;
return b.bFctn();
}
};
struct B : A<B>
{
int bFctn()
{
return 5;
}
};
int main()
{
A<B> a;
return a.callFctn();
}