I'm creating a C-wrapper for a C++ class:
class IObject {
public:
virtual int getValue() const;
virtual ~IObject() = default;
};
class Object: public IObject {
public:
virtual int getValue() const { return 123; }
};
Inspired openh264's C API, I have the following code:
// object.h
#pragma one
#ifdef __cplusplus
class IObject {
public:
virtual int getValue() const = 0;
virtual ~IObject() = default;
};
extern "C" {
#else
typedef struct IObjectVtable IObjectVtable;
typedef IObjectVtable const* IObject;
struct IObjectVtable {
int (*getValue)(IObject*);
};
#endif
int makeObject(IObject**);
int freeObject(IObject*);
#ifdef __cplusplus
} // extern "C"
#endif
// object.cpp
#include "object.h"
class Object : public IObject {
public:
virtual int getValue() const override { return 123; }
};
extern "C" {
int makeObject(IObject** obj) {
*obj = new Object;
if (*obj == nullptr) {
return 1;
}
return 0;
}
int freeObject(IObject* obj) {
delete obj;
return 0;
}
}
In main.c, I use Object as follows:
#include <stdio.h>
#include "object.h"
int main() {
IObject* obj;
makeObject(&obj);
printf("%d\n", (*obj)->getValue(obj)); /** Calling getValue */
freeObject(obj);
return 0;
}
The code compiles and correctly prints "123", but I need to pass obj as an argument of getValue(). Is it possible to avoid this, i.e., simply call obj->getValue()?
According to the documentation, openh264 can do that, but I don't understand how/why it works:
ISVCDecoder *pSvcDecoder; //similar to IObject* obj;
WelsCreateDecoder(&pSvcDecoder); //similar to makeObject(&obj);
pSvcDecoder->Initialize(&sDecParam); //similar to obj->getValue();
// not (*obj)->getValue(obj)
Related
I am having a segmentation fault problem with the following main function. "base" is an instance of the base class, "baseOne" is an instance of a derived class. When I call base->foo() inside the scope, the function works properly, but when I call it outside the scope, I get a segmentation fault. How can I make base->foo() work outside of the scope?
main.cpp
#include "Handler.hpp"
#include "Derived.hpp"
using namespace std;
int main(){
Base* base;
{
Derived_factory factoryOne("Derived.so");
std::unique_ptr<Base> baseOne = factoryOne.create();
Base* b;
b = baseOne.release();
base=b;
base->foo();
}
base->foo();
return 0;
}
On the other hand, the following code works, even though it is not appropriate for my program.
#include "Handler.hpp"
#include "Derived.hpp"
using namespace std;
int main(){
Base* base;
{
Base* b = new Derived();
base=b;
base->foo();
}
base->foo();
return 0;
}
The rest of the code is below.
base.hpp
class Base {
public:
virtual ~Base() {}
virtual void foo() = 0;
};
using Base_creator_t = Base *(*)();
derived.hpp
#include "Base.hpp"
class A{
public:
int k;
void printsomething(){
std::cout<<"class A "<<k<<std::endl;
};
};
class Derived: public Base {
public:
A a;
void virtual foo(){
std::cout<<"Hello Foo! Derived Class"<<std::endl;
returnA();
};
void printA(){
a.k = 10;
a.printsomething();
};
};
extern "C" {
Base * create() {
return new Derived;
}
}
handler.hpp
#include <dlfcn.h>
#include "Base.hpp"
#include <iostream>
#include <memory>
class Derived_factory {
public:
Derived_factory(char* path) {
handler = dlopen(path, RTLD_NOW);
if (! handler) {
throw std::runtime_error(dlerror());
}
Reset_dlerror();
creator = reinterpret_cast<Base_creator_t>(dlsym(handler, "create"));
Check_dlerror();
}
std::unique_ptr<Base> create() const {
return std::unique_ptr<Base>(creator());
}
~Derived_factory() {
if (handler) {
dlclose(handler);
}
}
private:
void * handler = nullptr;
Base_creator_t creator = nullptr;
static void Reset_dlerror() {
dlerror();
}
static void Check_dlerror() {
const char * dlsym_error = dlerror();
if (dlsym_error) {
throw std::runtime_error(dlsym_error);
}
}
};
I'm trying to practice "Observer Design Pattern". When I thought a abstract's pure virtual method has been override by it's derived class, a error occurred.
There is a observer which is an abstract class in a independent file:
#ifndef DESIGN_PATTERNS_OBSERVER_H
#define DESIGN_PATTERNS_OBSERVER_H
#include "subject.h"
class Subject;
class Observer{
protected:
Observer();
public:
virtual ~Observer();
virtual void update(Subject *the_changed_subject) = 0;
};
Observer::Observer() {}
Observer::~Observer() {}
#endif //DESIGN_PATTERNS_OBSERVER_H
Observer defined a pure virtual method "update" which overrides as follow:
#ifndef DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#define DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#include <iostream>
#include "observer.h"
#include "concrete_subject.h"
class ConcreteObserver : public Observer{
public:
void update(Subject *the_changed_subject) override {
auto cs = dynamic_cast<ConcreteSubject *>(the_changed_subject);
std::cout << "status changed to " << cs->get_status() << std::endl;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_OBSERVER_H
And also there is a subject which is an abstract class too.The error "pure virtual method called" happened in "notify" method where I had marked.
From debug, it seems "notify" uses Observer's "update" rather than ConcreteObserver's.
However,in main function the _observers should stored pointers of ConcreteObservers which override "update".
#ifndef DESIGN_PATTERNS_SUBJECT_H
#define DESIGN_PATTERNS_SUBJECT_H
#include <list>
#include "observer.h"
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
#endif //DESIGN_PATTERNS_SUBJECT_H
And it has a derived class "ConcreteSubject":
#ifndef DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#define DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#include "subject.h"
class ConcreteSubject : public Subject {
private:
int status;
public:
ConcreteSubject() {
status = 0;
}
void set_status(int s) {
this->status = s;
Subject::notify();
}
int get_status() {
return status;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_SUBJECT_H
The main function:
#include <iostream>
#include <vector>
#include "singleton.h"
#include "observer/concrete_subject.h"
#include "observer/concrete_observer.h"
void test2() {
ConcreteSubject concreteSubject;
std::vector<ConcreteObserver> observers;
for (int i = 0; i < 5; ++i) {
ConcreteObserver observer = ConcreteObserver();
concreteSubject.attach(&observer);
observers.push_back(observer);
}
concreteSubject.set_status(2);
}
int main() {
test2();
return 0;
}
As I mentioned before, the _observers of ConcreteSubject's super class Subject should stored pointers of ConcreteObservers which override "update" already.
I don't understand why Observer's "update" still called.
Here is another strange thing.I make a small test has almost the same relationship of classes I showed.But no error occured.
class ABaseA{
public:
virtual void do_some() = 0;
};
class MidA : public ABaseA{
public:
void do_some() override {
cout << "real do some" << endl;
}
};
class ABaseB{
private:
list<ABaseA*> *bases;
public:
ABaseB() {
bases = new list<ABaseA*>();
}
virtual ~ABaseB() = default;
virtual void add(ABaseA* item) {
bases->push_back(item);
}
virtual void do_active() {
for(ABaseA *p : *bases) {
p->do_some();
}
}
};
class MidB : public ABaseB{
public:
MidB() = default;
void active() {
ABaseB::do_active();
}
};
void test3() {
MidA midA;
MidB midB;
midB.add(&midA);
midB.active();
}
The only difference is this code is in one file.
In the file of Subject.h you should be transfer below code to Subject.cpp:
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
Also you should be add class Observer; in top of Subject.h
#include <list>
#include "Observer.h"
class Observer; //you should be add this line
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};
Can I do an defined constructor which contains an object from another class?
If i can do how is defined.
this is an example.I do classes and how could be defined the constructor of class "Abonati" which contains an object "abonament"
I need that because i have another class which contain a vector of "abonati"
#pragma once
#include"abonament.h"
#include<iostream>
#include<vector>
using namespace std;
class abonati
{
char*nume_abonat;
int nr_telefon;
char *numefisier;
abonament *a;
public:
abonati();
abonati(char*, int , char *,abonament *);
abonati(abonati&a);
void Send();
~abonati();
};
`#pragma once
#include"abonati.h"
class abonament
{
protected:
int cost;
public:
abonament();
abonament(int costa);
virtual ~abonament();
};
#include "abonament.h"
abonament::abonament()
{
this->cost = 0;
}
abonament::abonament(int costa)
{
this->cost = costa;
}
abonament::~abonament()
{
}
`
I guess you would like to pass an class instance to another class constructor
Here is an example
#include <iostream>
class A
{
public:
A(int value) : m_int(value) {}
int GetInt() { return m_int; }
private:
int m_int;
};
class B
{
public:
B(A& a) : m_int(a.GetInt()) {} // Here constructor expects instance of class A
int GetInt() { return m_int; }
private:
int m_int;
};
int main()
{
A a(2);
B b(a); // Pass an object of class A to constructor of class B
std::cout << b.GetInt() << std::endl;
return 0;
}
Prints
2
I was just wondering if there was a way to create a c wrapper API for a c++ class that has inheritance.
Consider the following:
class sampleClass1 : public sampleClass{
public:
int get() { return this.data *2; };
void set(int data);
}
class sampleClass : public sample{
public:
int get() { return this.data; }
void set(int data) {this.data = data; }
}
class sample {
public:
virtual int get();
virtual void set(int data);
private:
int data;
}
How would I wrap the sampleClass1 to make it work in a c context ???
thanks,
First, your sample should really get a proper virtual dtor.
Next, just add one free function with C-binding for each function which is part of the interface, simply delegating:
"sample.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct sample sample;
sample* sample_create();
sample* sample_create0();
sample* sample_create1();
void sample_destroy(sample*);
int sample_get(sample*);
void sample_set(sample*, int);
#ifdef __cplusplus
}
#endif
"sample-c.cpp"
#include "sample.h" // Included first to find errors
#include "sample.hpp" // complete the types and get the public interface
sample* sample_create() {return new sample;}
sample* sample_create0() {return new sampleClass;}
sample* sample_create1() {return new sampleClass1;}
void sample_destroy(sample* p) {delete p;}
int sample_get(sample* p) {return p->get();}
void sample_set(sample* p, int x) {p->set(x);
"sample.hpp"
// Your C++ header here, with class definition
"sample.cpp"
#include "sample.hpp" // Included first to find errors
// Implement the class here
I'm getting an error in WinImp.h that says 'Root' has not been declared. If I don't use the scope operator (class WinImp : public BaseDef) the error is error: expected class-name before '{' token). Anyone know why this is happening?
Root.h
class Root {
public:
class BaseDef {
public:
virtual void foo() = 0;
virtual void bar() = 0;
};
private:
#ifdef _WIN32
friend class WinImp;
#else
friend class NixImp;
#endif
BaseDef* imp;
BaseDef* getImp();
public:
Root() : imp(getImp()) {}
void foo();
void bar();
};
Root.cpp
#include "Root.h"
void Root::foo() {
imp->foo();
}
void Root::bar() {
imp->bar();
}
WinImp.h
#ifdef _WIN32
#include "Root.h"
class WinImp : public Root::BaseDef {
public:
void foo();
void bar();
};
#endif
WinImp.cpp
#include "WinImp.h"
#ifdef _WIN32
void WinImp::foo() {
}
void WinImp::bar() {
}
Root::BaseDef* Root::getImp() {
return static_cast<BaseDef*>(new WinImp());
}
#endif
You are accessing BaseDef interfaces in Root, so they suppose to be public:
class BaseDef
{
public:
virtual void foo() = 0;
virtual void bar() = 0;
};
In WinImp.cpp, foo(), bar() need return type and they are not inside Root scope, should be:
void WinImp::foo() { }
void WinImp::bar() { }
Fix WinImp.cpp to look like this:
#include "WinImp.h"
#ifdef _WIN32
// WinImp is not scoped within Root
void WinImp::foo() {
}
void WinImp::bar() {
}
Root::BaseDef* Root::getImp() {
return dynamic_cast<BaseDef*>(new WinImp());
}
#endif