Cannot call member function without object = C++ - c++

I am brushing up again and I am getting an error:
Cannot call member function without object.
I am calling like:
FxString text = table.GetEntry(obj->GetAlertTextID());
FxUChar outDescription1[ kCP_DEFAULT_STRING_LENGTH ];
IC_Utility::CP_StringToPString(text, &outDescription1[0] );
The line: IC_Utility::CP_StringToPString(text, &outDescription1[0] ); is getting the error
My function is:
void IC_Utility::CP_StringToPString( FxString& inString, FxUChar *outString)
{
}
I know it has to be something simple I am missing.

If you've written the CP_StringToPString function, you need to declare it static:
static void IC_Utility::CP_StringToPString( FxString& inString, FxUChar *outString)
Alternatively, if it's a function in third-party code, you need to declare an IC_Utility object to call it on:
IC_Utility u;
u.CP_StringToPString(text, &outDescription1[0] );

Your method isn't static, and so it must be called from an instance (sort of like the error is saying). If your method doesn't require access to any other instance variables or methods, you probably just want to declare it static. Otherwise, you'll have to obtain the correct instance and execute the method on that instance.

You have to declare the function with the 'static' keyword:
class IC_Utility {
static void CP_StringToPString( FxString& inString, FxUChar *outString);

You need to declare the function static in your class declaration. e.g.
class IC_Utility {
// ...
static void CP_StringToPString(FxString& inString, FxUChar *outString);
// ...
};

"static" is the right answer. or, you can pass it a NULL "this" pointer if it's not used in the function:
((IC_Utility*)NULL)->CP_StringToPString(...);

Related

Is it possible to pass a member function to QueueUserAPC?

is there a possibility or a workaround to pass a member function to the Windows API function QueueUserAPC()?
Okay, I could pass a static member function.
But then I won't have full access to local member variables...
So is there a possibility to combine both, passing as member function and full access to non-static member variables?
I tried to work out a solution related to this but without any success yet.
Hopefully someone got an idea to solve this.
This is a kind of standard pattern to use when having C-style callbacks call your C++ functions.
You create a free function (or static member) that forwards the call ...
VOID CALLBACK ForwardTo_MyClass_func( _In_ ULONG_PTR dwParam )
{
auto* p = (MyClass*)dwParam;
p->func();
}
... and you then set it up by passing the instance pointer as the third parameter to QueueUserAPC:
QueueUserAPC( ForwardToMyClass_func, hThread, (ULONG_PTR)pMyClass );
If you need further arguments, you will have to create some kind of structure to hold both the instance pointer and the arguments.
The answer is no.
Windows API has a C interface, and therefor cannot handle name mangled signatures, such as C++ member functions. The function you pass must be a C style free function.
By the way, nesting it in a namespace is acceptable, if less scalable:
namespace apc_stuff
{
static MyStruct some_static_data;
static void __stdcall MyApcFunc(ULONG_PTR data); // PAPCFUNC
};
using namespace apc_stuff;
MyClass::DoSomething(...)
{
auto my_data = new MyData(...);
auto data = reinterpret_cast<ULONG_PTR>(my_data);
QueueUserAPC(MyApcFunc, hThread, data)
}
/*static*/ void __stdcall apc_stuff::MyApcFunc(ULONG_PTR data)
{
auto my_data = reinterpret_cast<MyData *>(data);
//
// use my_data
// use some_static_data
//
}

Passing Function Pointer of an interface function

I have following situation, there are two interfaces:
interface ILLShapeAttribute
{
virtual void DefineAttribute(const char* pszAttributeName, VARIANT* pvAttributeData) = 0;
};
interface ILLShapeNotification
{
virtual bool IsUsed(const RECT& rcBounds) = 0;
virtual void DefineAttribute(const char* pszAttributeName, VARIANT* pvAttributeData) = 0;
}
And 2 functions:
INT LlShapeGetAttributeList(LPCWSTR pwszShapefileName, ILLShapeAttribute* pIAttrInfo);
INT LlShapeEnumShapes(LPCWSTR pwszShapefileName, ILLShapeNotification* pIInfo);
In those both functions I want to call the same function IterateRecords2 which should get the pointer to the function DefineAttribute, e.g. ILLShapeAttribute::DefineAttribute and ILLShapeNotification::DefineAttribute
I defined it this way:
void IterateRecords2(ifstream& file, void (*pDefineAttribute)(const char*, VARIANT*))
{
pDefineAttribute(NULL, NULL); //will be called with real values
}
Until now the code compiles and everythig is fine. But then I try to call the IterateRecords2 like
IterateRecords2(file, pIAttrInfo->DefineAttribute);
or
IterateRecords2(file, pIInfo->DefineAttribute);
I get the compiler error:
error C3867: 'ILLShapeAttribute::DefineAttribute': function call missing argument list; use '&ILLShapeAttribute::DefineAttribute' to create a pointer to member
Please: I know, that ILLShapeNotification could inherit from ILLShapeAttribute and then pass *ILLShapeAttribute instead of function pointer but I want to understand how it works.
Question: how can I pass the pointer to DefineAttribute to IterateRecords2?
Question: how can I pass the pointer to DefineAttribute to IterateRecords2?
You can't.
A pointer-to-member-function is not compatible with a pointer to function, and even if it was, you'd need an object to call it on, you can't just call a member function without an object.
Some options are:
1) Take a pointer-to-member-function and pass an object.
This would solve your compiler error, but to be able to pass different types of object that are not related by inheritance you would need IterateRecords2 to be a template:
template<typename T>
void IterateRecords2(ifstream& file, T* obj, void (T::*pDefineAttribute)(const char*, VARIANT*))
{
obj->pDefineAttribute(NULL, NULL);
}
Now you can use it like this:
IterateRecords2(file, pIAttrInfo, &ILLShapeAttribute::DefineAttribute);
or:
IterateRecords2(file, pIInfo, &ILLShapeNotification::DefineAttribute);
2) Bind an object and its member function into a callable type, and pass that:
void IterateRecords2(ifstream& file, std::function<void(const char*, VARIANT*)> DefineAttribute)
{
DefineAttribute(NULL, NULL);
}
Then call it like:
IterateRecords2(file, std::bind(&ILLShapeAttribute::DefineAttribute, pIAttrInfo));
If you can't use std::function and std::bind you can replace them with boost::function and boost::bind

Binding singleton in SLB

I have singleton class and I would like to bind it for lua to use. I'm using SLB (Simple Lua Binder). I really have no idea how to do this. All my ideas just dont work. Anyone?
void Logger::export_class_to_lua(SLB::Manager *m) {
SLB::Class< Logger, SLB::Instance::NoCopyNoDestroy >("Logger",m)
.set("getInstance",&Logger::getInstance)
.set("log",&Logger::log)
.set("info",&Logger::info)
.set("warning",&Logger::warning)
.set("error",&Logger::error)
.set("fatal",&Logger::fatal);
}
Using your code do:
void Logger::export_class_to_lua(SLB::Manager *m) {
SLB::Class< Logger, SLB::Instance::NoCopyNoDestroy >("Logger",m)
//.set("getInstance",&Logger::getInstance) // OMIT THIS
.set("log",&Logger::log)
.set("info",&Logger::info)
.set("warning",&Logger::warning)
.set("error",&Logger::error)
.set("fatal",&Logger::fatal);
// Next we set global variable within LUA to access the Singleton
SLB::setGlobal<Logger*>(&(*lua_State), getInstance(), "logger");
}
lua_State will be a pointer to whatever lua_State you created.
"logger" is the name of the object/class/variable you use within LUA to access the Singleton.
So for example; inside of LUA you would do:
logger:log("Logging some information.")
logger:error("An error has occured.")
Assuming your log and error functions take const char* or something.

V8 FunctionTemplate Class Instance

I have the following class:
class PluginManager
{
public:
Handle<Value> Register(const Arguments& args);
Handle<ObjectTemplate> GetObjectTemplate();
};
I want the Register method to be accessible from JavaScript. I add it to the global object like this:
PluginManager pluginManagerInstance;
global->Set(String::New("register"), FunctionTemplate::New(pluginManagerInstance.Register));
It throws the following error:
'PluginManager::Register': function
call missing argument list; use
'&PluginManager::Register' to create a
pointer to member
I tried to do that, but it doesn't work either. And it's not correct, because I want it to call the Register method of the pluginManagerInstance.
Except for making the Register method static or global, any ideas?
Thanks.
You're trying to bind two things at once: the instance and the method to invoke on it, and have it look like a function pointer. That unfortunately doesn't work in C++. You can only bind a pointer to a plain function or a static method. So image you add a static "RegisterCB" method and register it as the callback:
static Handle<Value> RegisterCB(const Arguments& args);
...FunctionTemplate::New(&PluginManager::RegisterCB)...
Now where do you get the pluginManagerInstance from? For this purpose, most callback-registration apis in V8 have an additional "data" parameter that will get passed back to the callback. So does FunctionTemplate::New. So you actually want to bind it like this:
...FunctionTemplate::New(&PluginManager::RegisterCB,
External::Wrap(pluginManagerInstance))...
The data is then available through args.Data() and you can delegate to the actual method:
return ((PluginManager*)External::Unwrap(args.Data())->Register(args);
This can surely be made a little easier with some macro.
You will likely need to make it static. Don't forget member functions take a hidden this parameter as the first argument. Because of this, they rarely work well as function pointer prototypes.
For an example take a look at the code in this tutorial. The same method mernst suggests above is used to send a pointer to this object, to the log function.
in header:
virtual void log(const string &str);
static Handle<Value> logCallback(const Arguments &args);
Local<FunctionTemplate> makeStaticCallableFunc(InvocationCallback func);
Local<External> classPtrToExternal();
////////////////////////////////////////////////////////////////////////
//
// Converts an External to a V8TutorialBase pointer. This assumes that the
// data inside the v8::External is a "this" pointer that was wrapped by
// makeStaticCallableFunc
//
// \parameter data Shoudld be v8::Arguments::Data()
//
// \return "this" pointer inside v8::Arguments::Data() on success, NULL otherwise
//
////////////////////////////////////////////////////////////////////////
template <typename T>
static T *externalToClassPtr(Local<Value> data)
{
if(data.IsEmpty())
cout<<"Data empty"<<endl;
else if(!data->IsExternal())
cout<<"Data not external"<<endl;
else
return static_cast<T *>(External::Unwrap(data));
//If function gets here, one of the checks above failed
return NULL;
}
implementation:
////////////////////////////////////////////////////////////////////////
//
// Wrap a callback function into a FunctionTemplate, providing the "this"
// pointer to the callback when v8 calls the callback func
//
// \parameter func Static callback to be used in FunctionTemplate
//
// \return Local<FunctionTemplate> containing func
//
////////////////////////////////////////////////////////////////////////
Local<FunctionTemplate> V8TutorialBase::makeStaticCallableFunc(InvocationCallback func)
{
HandleScope scope;
Local<FunctionTemplate> funcTemplate = FunctionTemplate::New(func, classPtrToExternal());
return scope.Close(funcTemplate);
}
////////////////////////////////////////////////////////////////////////
//
// Makes the "this" pointer be an external so that it can be accessed by
// the static callback functions
//
// \return Local<External> containing the "this" pointer
////////////////////////////////////////////////////////////////////////
Local<External> V8TutorialBase::classPtrToExternal()
{
HandleScope scope;
return scope.Close(External::New(reinterpret_cast<void *>(this)));
}
Handle<Value> V8TutorialBase::logCallback(const Arguments &args)
{
HandleScope scope;
.....
V8TutorialBase *objPtr = externalToClassPtr<V8TutorialBase>(args.Data());
String::Utf8Value val(Local<String>::Cast(args[0]));
objPtr->log(*val); // log is a non static member function
// or you can directly do anything that you would do in a member function using the objPtr
return v8::Null();
}
If you want to call that method, you have to add parentheses:
lobal->Set( String::New("register")
, FunctionTemplate::New(pluginManagerInstance.Register()) );
^^
If you want to take its address, you have to add a &:
lobal->Set( String::New("register")
, FunctionTemplate::New(&PluginManager::Register) );
^
(Which is exactly what the error message says.)

Function Pointer from base class

i need a Function Pointer from a base class. Here is the code:
class CActionObjectBase
{
...
void AddResultStateErrorMessage( const char* pcMessage , ULONG iResultStateCode);
...
}
CActionObjectCalibration( ): CActionObjectBase()
{
...
m_Calibration = new CCalibration(&CActionObjectBase::AddResultStateErrorMessage);
}
class CCalibration
{
...
CCalibration(void (CActionObjectBase::* AddErrorMessage)(const char*, ULONG ));
...
void (CActionObjectBase::* m_AddErrorMessage)(const char*, ULONG );
}
Inside CCalibration in a Function occurs the Error. I try to call the Function Pointer like this:
if(m_AddErrorMessage)
{
...
m_AddErrorMessage("bla bla", RSC_FILE_ERROR);
}
The Problem is, that I cannot compile. The Error Message says something like:
error C2064: Expression is no Function, that takes two Arguments.
What is wrong?
regards
camelord
You need to provide an object on which you call the member function:
CActionObjectBase* pActionObjectBase /* = get pointer from somewhere */ ;
(pActionObjectBase->*m_AddErrorMessage)("bla bla", RSC_FILE_ERROR);
Unlike normal object and function pointers, pointers to members can only be deferenced using an object of the appropriate type via the .* (for objects and references) or ->* (for pointers to objects) operators.
You need to invoke m_AddErrorMessage on an object, something like:
(something->*m_AddErrorMessage)(...)