Is it possible to have an exported function in a DLL return a static member of an exported class? - plugins

I'm working on a plug-in protocol of sorts. The idea is that there's a base clase PCOperatorBase and that plugins would subclass this base class to provide specific functionality through a "process" virtual method that they override. The subclasses also should have a static struct member that hold typical plugin info: plug name, type and subtype. This info is used by another class (a PCOperatorManager) to know what types of plugins is dealing with. And I thought about having it be a static member so that there's no need to instantiate a plug to merely find out about the type of operator it is.
I have the following classes:
PCOperatorBase.h the superclass from which to derive all other plugs:
#ifdef PCOPERATORBASE_EXPORTS
#define PCOPERATORBASE_API __declspec(dllexport)
#else
#define PCOPERATORBASE_API __declspec(dllimport)
#endif
class PCOPERATORBASE_API PCOperatorBase
{
public:
typedef struct OperatorInfo
{
wchar_t* name;
wchar_t* type;
wchar_t* subtype;
} OperatorInfo;
PCOperatorBase(void);
virtual ~PCOperatorBase(void);
virtual int process(int* inBuffer, int* outBuffer, int bufferSize);
};
And then, for instance, a subclass:
BlackNWhite.h: a RGB->black / white operator -- yes, these are going to be graphics plugs, and disregard the types for the in / out buffers.. they are merely placeholders at this point.
#ifdef BLACKNWHITE_EXPORTS
#define BLACKNWHITE_API __declspec(dllexport)
#else
#define BLACKNWHITE_API __declspec(dllimport)
#endif
// This class is exported from the BlackNWhite.dll
class BLACKNWHITE_API CBlackNWhite : PCOperatorBase
{
public:
static PCOperatorBase::OperatorInfo* operatorInfo;
CBlackNWhite(void);
virtual ~CBlackNWhite(void);
//virtual int process(int* inBuffer, int* outBuffer, int bufferSize);
};
BLACKNWHITE_API CBlackNWhite* getOperatorInstance();
BLACKNWHITE_API const PCOperatorBase::OperatorInfo* getOperatorInfo();
And here the implementation file:
BlackNWhite.cpp:
#include "stdafx.h"
#include "BlackNWhite.h"
BLACKNWHITE_API CBlackNWhite* getOperatorInstance()
{
return new CBlackNWhite();
}
BLACKNWHITE_API const PCOperatorBase::OperatorInfo* getOperatorInfo()
{
return CBlackNWhite::operatorInfo;
}
CBlackNWhite::CBlackNWhite()
{
}
CBlackNWhite::~CBlackNWhite()
{
}
Now, I've tried a few approaches but I can't get the DLL to compile, because of the static member.The linker throws:
\BlackNWhite.lib and object c:\Projects\BlackNWhite\Debug\BlackNWhite.exp
1>BlackNWhite.obj : error LNK2001: unresolved external symbol "public: static struct PCOperatorBase::OperatorInfo * CBlackNWhite::operatorInfo" (?operatorInfo#CBlackNWhite##2PAUOperatorInfo#PCOperatorBase##A)
1>c:\Projects\BlackNWhite\Debug\BlackNWhite.dll : fatal error LNK1120: 1 unresolved externals
I thought that since the struct is defined inside the base class and the base class is exporting, the struct would export too. But I guess I'm wrong?
So how should I be doing it?
And regardless, is there a better approach to having the plugs' factory export their name,type and subtype without the need for instantiation than a static class member? For example, a resource file? or even another extern "C" function could return this info.. But I just felt that since it's C++ it makes the most sense to encapsulate this data (which is about the class as a factory itself) within the class, whether through a member or a method.

It doesn't have anything to do with DLLs, you declared the static member but you forgot to define it. Add this line to BlackNWhite.cpp:
PCOperatorBase::OperatorInfo* CBlackNWhite::operatorInfo = NULL;

Related

Cannot use make_constructor in boost::python when declaring external constructor

I'm trying to defined an external constructor when porting a class to python, by using make_constructor absolutely fails. When I try:
#include <boost/python/numpy.hpp>
using boost::python;
class foo
{
int i;
public:
foo(int i) : i(i){}
};
foo foo_create(int i){return foo(i);}
BOOST_PYTHON_MODULE(bar)
{
class_<foo>("foo")
.def("__init__", make_constructor(&foo_create));
}
I get the following error
error: no type named ‘element_type’ in ‘class foo’
I tried using noinit and init() with the same result. What am I doing wrong?
Awe found the problem, part of it being the really sparse documentation on make_construction. I needed to return a ptr to a new instance like so (in this case I made them shared pointers):
#include <boost/python/numpy.hpp>
#include <memory>
using boost::python;
class foo
{
int i;
public:
foo(int i) : i(i){}
};
std::shared_ptr<foo> foo_create(int i){return std::shared_ptr<foo>(foo(i));}
BOOST_PYTHON_MODULE(bar)
{
class_<foo, std::shared_ptr<foo>>("foo")
.def("__init__", make_constructor(&foo_create));
}
The documentation on make_constructor is really sparse, but there is some discussion here: https://wiki.python.org/moin/boost.python/HowTo under point "9".

Classes (located in different headers) that use each other's objects

The class called Universes uses a data member of type States, whilst States uses an object of type Universes. I'm using Visual C++ 2010 Express (if that makes any difference).
States.h:
class Universes;
extern Universes universe;
class States
{
public:
int relations;
States();
};
States::States()
{
relations = universe.state_no;
}
Universes.h
#include "States.h"
class Universes
{
public:
States state;
int state_no;
};
Test.cpp
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include "Universes.h"
using namespace System;
int main(array<System::String ^> ^args)
{
Universes universe;
_getch();
return 0;
}
I keep getting the following errors:
States.h(16): error C2027: use of undefined type 'Universes'
States.h(1) : see declaration of 'Universes'
States.h(16): error C2228: left of '.state_no' must have class/struct/union
At the point where you try to access universe.state_no, the Universes class is incomplete (it's forward-declared).
A clean way to fix this is to move the definition of States::States into States.cpp, and make sure States.cpp #includes Universes.h.

boost thread+signals: mem_fn error, invalid use of non-static member function

I am trying to get acquainted with boost thread and signals. I have therefore implemented this very simple code consisting of a class (Class1) implementing a thread. I'd like this class to provide services as result of signals reception. To this end I have just started to exploit the signal boost library but I am getting this error:
/home/andrea/libs/boost_1_50_0/boost/bind/mem_fn.hpp:359:22: error: invalid use of non-static member function
when I try to compile it in the Eclipse environment with gcc. Is there anything wrong with the singleton or is the binding to the instance method?
Here is Class1.cpp
#include "Class1.hpp"
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
#include "Package1.hpp"
Class1::Class1(){
boost::thread thread(boost::bind(&Class1::classifierBehavior,this));
};
void Class1::classifierBehavior(){
service.run();
Package1Signals::getInstance()->signal1.connect(boost::bind(&Class1::method1, boost::ref(*this)));
};
void Class1::method1(Signal1 signal1){}
And Package1.hpp
#ifndef PACKAGE1_HEADER
#define PACKAGE1_HEADER
#include <boost/signal.hpp>
struct Signal1{
int foo;
};
class Package1Signals{
private:
Package1Signals();
static Package1Signals * instance;
public:
boost::signal<void (Signal1)> signal1;
static Package1Signals * getInstance(){
if(!instance){
instance = new Package1Signals();
}
return instance;
};
};
#endif
Your binder should have 1 argument:
boost::bind(&Class1::methpod1, boost::ref(*this), _1)

XCode compilation error for C++ code

I am trying to use my C++ classes for an iPhone app. I got 2 compilation errors in XCode that I do not quite understand. Here is the first one, in this header file myApps.h, I declare a class myApps and a struct PointF:
#pragma once
struct PointF {
float x;
float y;
}; // **compilation error message here :Multiple types in one declaration**
class myClass {
...
}
The second error is in a header file too,
#pragma once
class myClass1;
class myClass2;
class MyClass
{
public:
MyClass(void *view);
~MyClass();
virtual void Draw(myClass1 *c1);
//Error: Candidate is virtual void MyClass::Draw(myClass1 *)
virtual void Move(myClass2 c2[], myClass1 *c1, void *callback);
//Error: Candidate is virtual void MyClass::Move((myClass2, myClass1*, void*)
};
Thanks for your help
Ok, I don't know if this will help you but, from what I see:
myClass should have a semicolon at the end:
class myClass {
...
};
For the Candidate is virtual void MyClass::Draw(myClass1 *) below the last function of your class:
using myClass1::Draw;
using myClass1::Move;
since you probably have a method Draw and Move in myClass1... More on it here. It's hard to figure out exactly since I can't see the stuff in myClass1 and myClass2.
Just check Whether your file extension is .m or .mm for C++ files it must be .mm extension.

Doxygen for C++ template class member specialization

When I write class templates, and need to fully-specialize members of those classes, Doxygen doesn't recognize the specialization - it documents only the generic definition, or (if there are only specializations) the last definition. Here's a simple example:
===MyClass.hpp===
#ifndef MYCLASS_HPP
#define MYCLASS_HPP
template<class T> class MyClass{
public:
static void foo();
static const int INT_CONST;
static const T TTYPE_CONST;
};
/* generic definitions */
template<class T>
void MyClass<T>::foo(){
printf("Generic foo\n");
}
template<class T>
const int MyClass<T>::INT_CONST = 5;
/* specialization declarations */
template<> void MyClass<double>::foo();
template<> const int MyClass<double>::INT_CONST;
template<> const double MyClass<double>::TTYPE_CONST;
template<> const char MyClass<char>::TTYPE_CONST;
#endif
=== MyClass.cpp ===
#include "MyClass.hpp"
/* specialization definitions */
template<>
void MyClass<double>::foo(){
printf("Specialized double foo\n");
}
template<> const int MyClass<double>::INT_CONST = 10;
template<> const double MyClass<double>::TTYPE_CONST = 3.141;
template<> const char MyClass<char>::TTYPE_CONST = 'a';
So in this case, foo() will be documented as printing "Generic foo," INT_CONST will be documented as set to 5, with no mention of the specializations, and TTYPE_CONST will be documented as set to 'a', with no mention of 3.141 and no indication that 'a' is a specialized case.
I need to be able to document the specializations - either within the documentation for MyClass<T>, or on new pages for MyClass<double>, MyClass<char>. How do I do this? Can Doxygen even handle this? Am I possibly doing something wrong in the declarations/code structure that's keeping Doxygen from understanding what I want?
I should note two related cases:
A) For templated functions, specialization works fine, e.g.:
/* functions that are global/in a namespace */
template<class T> void foo(){ printf("Generic foo\n"); }
template<> void foo<double>(){ printf("Specialized double foo\n"); }
This will document both foo<T>() and foo<double>().
B) If I redeclare the entire template, i.e. template<> class MyClass<double>{...};, then MyClass<double> will get its own documentation page, as a seperate class. But this means actually declaring an entirely new class - there is no relation between MyClass<T> and MyClass<double> if MyClass<double> itself is declared. So I'd have to redeclare the class and all its members, and repeat all the definitions of class members, specialized for MyClass<double>, all to make it appear as though they're using the same template. Very awkward, feels like a kludge solution.
Suggestions? Thanks much :)
--Ziv
Further seeking indicates that this issue was an open bug, fixed in Doxygen 1.8.10.
This bug appears to be fixed 3 weeks ago