Is it possible to point a Typedef function pointer to a class member? - function-pointers

I am working with an executable that includes a DLL. For my testcase, I combined the code into a single executable. I am working with Visual Studio 2008 and Boost 1.43. I've tried researching this, but haven't found any clear answer. Thanks for the help.
In my main.h:
#include <string>
//These are normally defined in a seperate DLL
typedef std::string Typedef_func(const std::string & title);
void Register_My_Typedef(Typedef_func*);
//-------------------------------------------
class myClass
{
public:
std::string func_one(const std::string & title);
Typedef_func _test;
void run();
};
In my main.cpp:
#include "main.h"
#include <boost/bind.hpp>
std::string workingFunc(const std::string & title)
{
return "";
}
int main(int argc, char* argv[])
{
myclass* example;
example->run();
Register_My_Typedef(&workingFunc);//This works.
return 0;
}
void myClass::run()
{
//I want to point a Typedef_func* in a DLL to call myclass::func_one
Typedef_func* tf = boost::bind(&myClass::func_one, this, "test"); //This does not.
Register_My_Typedef(tf);
}
std::string myClass::funcOne(const std::string & title)
{
return "";
}
void Register_My_Typedef(Typedef_func* passedIn)
{
//Points the pointer in the DLL to passedIn
}
The DLL logic works fine when Register_My_Typedef is called on a function not in a class, but is it possible to call it from within a class? When I try to compile this code it returns:
When I try and compile in Windows XP with VS2008 I get:
Error C2440: 'initializing' : cannot convert from
'boost::_bi::bind_t' to 'Typedef_func (__cdecl *)' with
[
R=std::string,
F=boost::_mfi::mf1,
L=boost::_bi::list2,boost::_bi::value>
]
No user-defined-conversion operator available that can perform this
conversion, or the operator cannot be called.

The Answer is Typedef itself is class member for a static member function & behave differently to non-static however works best reading rather class function of user defined class main.

Related

what is the correct syntax function pointer list with class member?

I have a list of function pointers, the non-class member compiles without errors, but the class member compiles with errors:
error: cannot convert 'void (CVdmConfig::)()' to 'fp {aka void ()()}' in initialization
CVdmConfig::writeConfig is a void function.
typedef void (*fp)();
fp fpList[] = {&valvesCalib,&CVdmConfig::writeConfig} ;
What do I wrong ?
best regards
Werner
Without seeing the rest of your code, there is not much I can debug, but here is an example that works:
#include <iostream>
using namespace std;
void valvesCalib() {
cout << "inside function\n";
}
class CVdmConfig {
public:
static void writeConfig() {
cout << "inside method\n";
}
};
typedef void (*fp)();
fp fpList[] = {
&valvesCalib,
&CVdmConfig::writeConfig
};
int main()
{
for (auto f: fpList) {
f();
}
return 0;
}
/*
Output:
inside function
inside method
Program finished with exit code 0
*/
The problem was the missing static definition in the member function. But this leads into other problems with variables in the class. So I use a wrapper for this.

Compile Errors in Class with User Defined Functions

I am trying to build a class that stores a user-defined function inside of it for later use. I have decided to use the boost::function object to do so.
However, I get the following error on compile:
error: no match for ‘operator=’ in ‘((SomeClass*)this)->SomeClass::someFunction = ((SomeClass*)this)->SomeClass::DefaultFunction’
I do not understand this error, since someFunction and DefaultFunction should, as far as I can see, have the same types.
The code is shown below:
#include <boost/function.hpp>
class SomeClass{
private:
boost::function<int(int)> someFunction;
int DefaultFunction(int i);
public:
SomeClass();
~SomeClass();
void SetFunction(int (*f)(int));
};
int SomeClass::DefaultFunction(int i){
return i+1;
}
SomeClass::SomeClass(){
someFunction=DefaultFunction;
}
~SomeClass::SomeClass(){
}
void SomeClass::SetFunction(int (*f)(int i)){
someFunction=f;
}
void MyProgram(){
SomeClass s;
}
Can anyone offer any pointers as to how to construct such an object? Alternatively, iff there is a better way than the one I am attempting, could you explain it to me?
Kindest regards!
DefaultFunction is a member function of SomeClass.
Member function is called for some instance of SomeClass.
This function takes "hidden" pointer to SomeClass instance as its first parameter addition to int.
So member function is not the same as free function.
Your someFunction is object of boost::function, so it is wrapper for callable object.
Your requirements to that object are: take int and returns int.
In order to assign DefaultFunction (as member function) to someFunction you need to create this callable object.
Here you need to specify for which instance of SomeClass this object will be called, to do that use boost::bind:
SomeClass::SomeClass(){
someFunction=boost::bind(&SomeClass::DefaultFunction, this, boost::placeholders::_1);
}
In the code above you create callable object which will behave as
struct unnamedClass {
SomeClass* sc;
unnamedClass (SomeClass* sc) : sc(sc) {} // here sc is this of SomeClass
int operator()(int arg)
{
return sc->DefaultFunction(arg);
}
};
so when you invoke someFunction(10) it takes 10 as argument and call DefaultFunction for current this instance.
This
void SomeClass::SetFunction(int (*f)(int i)){
someFunction=f;
}
works because f is free function, which takes no hidden - pointer to class instance.
Using the answer of #rafix07, the following code compiled:
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/bind/placeholders.hpp>
class SomeClass{
private:
public:
SomeClass();
~SomeClass();
boost::function<int(int)> someFunction;
int DefaultFunction(int i);
void SetFunction(int (*f)(int));
};
int SomeClass::DefaultFunction(int i){
return i+1;
}
SomeClass::SomeClass(){
someFunction=boost::bind(&SomeClass::DefaultFunction, this, _1);
}
SomeClass::~SomeClass(){
}
void SomeClass::SetFunction(int (*f)(int i)){
someFunction=f;
}
int MyOwnProgram(int i){
return i+2;
}
void MyProgram(){
SomeClass s;
std::cout<<s.someFunction(2)<<std::endl;
s.SetFunction(MyOwnProgram);
std::cout<<s.someFunction(2)<<std::endl;
}
int main()
{
MyProgram();
}
The output from the program is:
3
4

boost.python MSVC12 linker errors when exposing classes with docstring_options

I regularly expose c++ classes to python using boost.python & MSVC 12 (dynamic linking). Recently I have been trying to include documentation using the "docstring_options" class. The documentation examples work fine:
http://www.boost.org/doc/libs/1_54_0/libs/python/doc/v2/docstring_options.html
However, when I include a class and expose it I get linker errors:
error LNK2019: unresolved external symbol "void __cdecl boost::throw_exception(class std::exception const &)" (?throw_exception#boost##YAXABVexception#std###Z) referenced in function "public: __thiscall boost::detail::shared_count::shared_count(void *,struct boost::python::converter::shared_ptr_deleter)"
I'm sure there is probably something simple I'm missing but I can't figure it out.
Many thanks in advance!
sample code spliced from the boost examples that gives this error for me.
#include <string>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/args.hpp>
#include <boost/python/docstring_options.hpp>
#include <boost/python.hpp>
struct World
{
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
int foo1(int i) { return i; }
int foo2(long l) { return static_cast<int>(l); }
int bar1(int i) { return i; }
int bar2(long l) { return static_cast<int>(l); }
namespace {
void wrap_foos()
{
using namespace boost::python;
def("foo1", foo1, arg("i"), "foo1 doc");
def("foo2", foo2, arg("l"), "foo2 doc");
}
void wrap_bars()
{
using namespace boost::python;
bool show_user_defined = true;
bool show_signatures = false;
docstring_options doc_options(show_user_defined, show_signatures);
def("bar1", bar1, arg("i"), "bar1 doc");
def("bar2", bar2, arg("l"), "bar2 doc");
class_<World>("World")
.def("greet", &World::greet)
.def("set", &World::set)
;
}
}
BOOST_PYTHON_MODULE(boost_py_doc_demo)
{
boost::python::docstring_options doc_options(false);
wrap_foos();
wrap_bars();
}
I compiled the latest version of boost (1.63) and now the problem has gone. I guess my old libraries were incomplete in some way.

pthread to invoke member func by wrapping it externally

I'm trying to invoke a member function by pthread by using an external wrapper but it doesn't quite work for me, I get a seg fault. Why is this?
Here's a little test program that displays the problem:
#include <iostream>
#include <pthread.h>
class test {
public:
test();
~test();
void RunTh(void);
private:
pthread_t *pid;
};
void *Run_wrp(void *context);
void test::RunTh(void)
{
while(1);
}
test::test()
{
pthread_create(pid,NULL,&Run_wrp,this);
}
test::~test(){}
int main(void) {
test tmp;
std::cin.get();
}
void *Run_wrp(void *context)
{
((test*)context)->RunTh();
}
Your pid member variable is just a pointer, not an actual pthread_t object.
Change it to:
private:
pthread_t pid;
Then create the new thread with:
pthread_create(&pid,NULL,&Run_wrp,this);
Also, if you want to keep everything contained in the class, you can make your Run_wrp() function a static member function of test, as long as you keep the same signature (return value/arguments). It needs to be static, as non-static functions take the this pointer to the class as a hidden argument, and thus end up with a different signature than what you need for pthread_create().

Unmanaged method member being used as a delegate in managed class

I have a project where I am expanding existing native C++ compatible code functionality for a customer-facing library by integrating a driver from a managed DLL, which seems like the opposite direction for most marshaling questions. Since there can be multiple devices using this one driver, each device needs to be its own object, with its own callback methods. This integration will take the form of a native wrapper DLL that exposes the native class interface to the customer-facing library, which will pass an instance of a member method callback function pointer to the DLL. I need to pass a native method member instance (non-static) as a delegate to the managed wrapper class. The managed wrapper class uses GetDelegateForFunctionPointer, which works to marshal static native pointers to a delegate, but I can't find any information if it works with instances. GetDelegateForFunctionPointer also takes a System::IntPtr argument for the function pointer, but I'm also not sure if System::IntPtr works for instances, and when compiling in VC++2008 I'm being presented an error C3867 for attempting this.
Managed wrapper header:
//somemanagedclass.hpp
#pragma once
using namespace System;
using namespace ExternalManagedLibrary;
namespace SomeNameSpace
{
public ref class SomeManagedClass
{
public:
SomeManagedClass();
~SomeManagedClass();
delegate void CallbackHandler(const wchar_t*, int);
CallbackHandler^ CallbackEvent;
void RegisterCallback(IntPtr callbackEvent);
private:
ExternalManagedClass^ externalManagedClass;
void OnCallback(Object^ sender, ValueEventArgs<String^>^ e);
};
}
Managed wrapper source:
//somemanagedclass.cpp
#include "somemanagedclass.hpp"
#include <vcclr.h>
using namespace System;
using namespace Runtime::InteropServices;
namespace SomeNameSpace
{
SomeManagedClass::SomeManagedClass()
{
externalManagedClass = gcnew ExternalManagedClass();
externalManagedClass->CallbackEvent += gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
}
SomeManagedClass::~SomeManagedClass()
{
externalManagedClass->CallbackEvent -= gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
}
void SomeManagedClass::OnCallback(Object^ sender, ValueEventArgs<String^>^ e)
{
String^ some_string = String::Copy(e->Value);
cli::pin_ptr<const wchar_t> pinned_string = &PtrToStringChars(some_string)[0];
const wchar_t* p = pinned_string;
CallbackEvent(pinned_string, some_string->Length);
}
void SomeManagedClass::RegisterCallback(IntPtr callbackEvent)
{
CallbackEvent = (CallbackHandler^)(Marshal::GetDelegateForFunctionPointer(callbackEvent, CallbackHandler::typeid));
}
}
Native wrapper interface:
//somenativeinterface.hpp
#ifdef DLL_EXPORT
#define IMPORT_EXPORT __declspec(dllexport)
#else
#define IMPORT_EXPORT __declspec(dllimport)
#endif //DLL_EXPORT
typedef void (*NativeCallback)(const unsigned char*, unsigned long);
class IMPORT_EXPORT SomeNativeInterface
{
public:
//class factory
static SomeNativeInterface* Create(void);
static void Destroy(SomeNativeInterface* clInterface);
virtual void CallbackInit(NativeCallback fnNativeCallbackInit);
};
Native wrapper header:
//somenativeclass.hpp
#pragma once
#include "somenativeinterface.hpp"
#include "somemanagedclass.hpp"
#include <vcclr.h>
using namespace SomeNameSpace;
class IMPORT_EXPORT SomeNativeClass : public SomeNativeInterface
{
public:
SomeNativeClass();
~SomeNativeClass();
void CallbackInit(NativeCallback fnNativeCallbackInit); //can this take an instance?
private:
NativeCallback fnNativeCallback;
void OnNativeCallback(const wchar_t* cString, int iSize);
gcroot<SomeManagedClass^> wrapper; //warning C4251
};
Native wrapper source:
//somenativeclass.cpp
#include "somenativeclass.hpp"
#include <vcclr.h>
#include <string.h>
using namespace System;
using namespace Runtime::InteropServices;
SomeNativeInterface* SomeNativeInterface::Create()
{
return ((SomeNativeInterface*) new SomeNativeClass());
}
void SomeNativeInterface::Destroy(SomeNativeInterface* instance)
{
delete instance;
}
SomeNativeClass::SomeNativeClass()
{
wrapper = gcnew SomeManagedClass();
}
SomeNativeClass::OnNativeCallback(const wchar_t* cString, int iSize)
{
std::auto_ptr<char> pcConvertedString(new char[iSize+1]);
size_t iCharsConverted;
if (wcstombs_s(&iCharsConverted, (char*)*pcConvertedString, iSize+1, cString, iSize) == 0)
{
if (iCharsConverted > 0xFFFFFFFF)
iCharsConverted = 0xFFFFFFFF; //truncate
fnNativeCallback((const unsigned char*)*pcConvertedString, (unsigned long)(iCharsConverted));
}
}
SomeNativeClass::CallbackInit(NativeCallback fnNativeCallbackInit)
{
fnNativeCallback = fnNativeCallbackInit;
wrapper->RegisterCallback(System::IntPtr(this->OnNativeCallback)); //error C3867
}