C++ Passing a function that's in a class to another function - c++

I'm trying to use lua_pushcfunction (Using lua 5.2). I have the struct
class readFunctions {
private:
std::ifstream file;
public:
static int readAll(lua_State*);
};
int readFunctions::readAll(lua_State *L){
std::string line;
std::string nam;
while (std::getline(file, line)) {
nam = nam + line;
}
std::cout << nam;
return 1;
}
readFunctions hand;
I use lua_pushcfunction(lua_state, hand.readAll) and get error: argument of type 'int (readFunctions::)(lua_State*)' does not match 'lua_CFunction {aka int (*)(lua_State*)}'|
How would I pass a method from a class to a function?

Try
lua_pushcfunction(lua_state, & readFunctions::readAll);
readAll is static so you dont need an instance; and you need its address not just the function (a function is like a value, so you need to give pushcfunction its address). However I can't remember if compiler will accept int (readFunctions::*)(lua_State*) as a int (*)(lua_State*), I have a feeling it might not but can't test it right now.
If you don't want a static method but a regular method: the method is part of an object (class instance), so to call it you need a this pointer; that won't work. But what might work is to use your static readFunctions::readAll, but when you call that function, the first parameter can be a light user data that is the readFunctions instance that you want to call.

Related

Can I call the function like that?

If I have a struct.
struct studentRec
{
string name;
int sid;
string major;
int cohort;
};
Then, I have a function.
int compare_MajorName(const studentRec& s1, const studentRec& s2)
Can I call the function like that?
String major = ECE;
list = new studentRec[n];
compare_MajorName(list[mid], major)
No you can't.
Your function parameters require studentRecs. A String cannot be converted to a studentRec automagically. It wouldn't make sense.
You have two possibilities:
make an overrided function which accepts a String as a second parameter
simply compare the name inside the struct with your String:
list[mid].name == major for exemple

Accessing a variable in a void function to be used in other functions? C++

Is it possible to access the d_nr variable outside of this function without returning it and how would I do that? I want to keep the return value void.
Not sure if this code is any help but this is the function in question. I wan't to access the d_nr variable outside of this function without returning it.
void read(data & P, string file_name)
{
int d_nr = 0, i = 0;
string line;
ifstream D(file_name);
while(getline(D, line))
{
istringstream iss (line);
iss >> P.string[d_nr];
while(iss.good())
{
iss >> P.var_1[i][d_nr] >> P.var_2[i][d_nr];
i++;
}
d_nr++;
i = 0;
}
D.close();
}
You can make it a parameter with reference call.
void read(data & P, string file_name, int &d_nr)
{
d_nr = 0;
...
You can pass a pointer to a extern variable
void read(data & P, string file_name, int *output)
and in the function update the output variable
*output = d_nr;
You can add one more parameter for the function. For example
void read(data & P, string file_name, int &d_nr )
{
d_nr = 0;
//...
Or if data is some class then you can simply add one more data member to this class. For example
void read(data & P, string file_name )
{
P.d_nr = 0;
//...
Is the problem that the function needs a specific signature, but you want additional information?
What, exactly, needs "access"? What kind of threading/process expectations do we have?
A simple global variable could work if there's no multi-threading. You could consider printing the value to stdout (this is probably a bad idea, but I have no idea what the context and requirements are, so it might be what you want.) Or, another related idea that might be terrible but it's hard to say without more detail on what you're doing - you could write it to the file.
Can you be more detailed about what you are trying to do? Probably a static variable would be best, assuming there's no threading issue.
Technically, you can't access a variable declared within the scope of the function if you are not in that scope yourself. Your two options to have access to that value outside of its scope is to either:
Copy its value to some other variable before leaving the scope (before the end of the function in this case). Or...
Declare a variable with a larger scope and use that from within your function.
Ways to do this with the first method include returning the value, or copying the value to a global - like this:
int global_dnr = 0;
void read(data & P, string file_name) {
int d_nr = 0, i = 0;
// The rest of your code as is...
global_dnr = d_nr;
}
Now you can access global_dnr anytime, and it should have the latest d_nr value. If your read function were a class method, you could assign d_nr to a class variable as well.
For approach 2, you don't declare d_nr in your function at all - you can declare a global variable, pass a variable by reference as a parameter (though this is technically equivalent to returning the variable) or access a class member directly. Here is an example using the global variable:
int d_nr = 0; // Here is the global declaration instead.
void read(data & P, string file_name) {
d_nr = 0; // Set variable to 0, but don't declare it here.
// The rest of your code as is...
}
These are your two options. Only the implementation details vary.

illegal call of non-static member function

I'm having trouble with this function below:
char* GetPlayerNameEx(int playerid)
{
char Name[MAX_PLAYER_NAME], i = 0;
GetPlayerName(playerid, Name, sizeof(Name));
std::string pName (Name);
while(i == 0 || i != pName.npos)
{
if(i != 0) i++;
int Underscore = pName.find("_", i);
Name[Underscore] = ' ';
}
return Name;
}
declaration:
char* GetPlayerNameEx(int playerid);
usage:
sprintf(string, "%s", CPlayer::GetPlayerNameEx(playerid));
Now my problem here is
Removed personal information.
If this has anything to do whith it which I doubt it does, this function is contained within a "Class" header (Declartion).
Also I have no idea why but I can't get the "Code" box to fit over correctly.
Illegal call of non-static member function means that you are trying to call the function without using an object of the class that contains the function.
The solution should be to make the function a static function.
This is normally what causes the error C2352:
class MyClass {
public:
void MyFunc() {}
static void MyFunc2() {}
};
int main() {
MyClass::MyFunc(); // C2352
MyClass::MyFunc2(); // OK
}
If making it static is not an option for you, then you have to create an instance of the class CPlayer.
Like this:
CPlayer myPlayer;
myPlayer.GetPlayerNameEx(playerid);
You cannot create these functions as static (without a lot of tweaking) because you are attempting to modify the data of a specific instance. To fix your problem:
class CPlayer
{
public:
// public members
// since you are operating on class member data, you cannot declare these as static
// if you wanted to declare them as static, you would need some way of getting an actual instance of CPlayer
char* GetPlayerNameEx(int playerId);
char* GetPlayerName(int playerId, char* name, int size);
private:
// note: using a std::string would be better
char m_Name[MAX_PLAYER_NAME];
};
// note: returning a string would be better here
char* CPlayer::GetPlayerNameEx(int playerId)
{
char* Name = new char[MAX_PLAYER_NAME];
memset(Name, MAX_PLAYER_NAME, 0);
GetPlayerName(playerId, m_Name, sizeof(m_Name));
std::string sName(m_Name);
std::replace(sName.begin(), sName.end(), '_', ' ');
::strncpy(sName.c_str(), Name, MAX_PLAYER_NAME);
return Name;
}
// in your usage
CPlayer player;
// ...
sprintf(string, "%s", player.GetPlayerNameEx(playerid));
CPlayer::GetPlayerNameEx(playerid)
You can't use the scope (::) operator on a class type to call a function unless it is a static function. To call a function on an object, you actually have to create the memory for that object first (via making a CPlayer variable somewhere) and then calling the function on that object.
Static functions are global and specifically do not mess with member variables of the class (unless they are also static) which makes them valid to call without the scope of an actual object instance.

C++ Wrapper to GNU Readline

I am trying to write a c++ wrapper for GNU Readline to be able to easily use custom completion but came across a small problem and can't think of a solution(I am still new to c++).
class ReadLine {
public:
ReadLine();
~ReadLine();
std::string exec ();
void enableHistory ();
private:
std::vector<std::string> keywordList;
bool history;
private:
static char** my_completion (const char*, int, int);
void* xmalloc (int);
char* generator (const char*, int);
char* dupstr (std::string);
};
cpp file:
std::string ReadLine::exec(){
rl_attempted_completion_function = my_completion;
std::string buf = "";
buf = readline("Command>>");
//enable auto-complete
rl_bind_key('\t',rl_complete);
if (buf[0]!=0)
add_history(buf.c_str());
return buf;
}
char** ReadLine::my_completion (const char* text, int start, int end) {
char** matches;
matches = NULL;
if (start == 0)
matches = rl_completion_matches(text, my_generator);
return matches;
}
My problem is the line
matches = rl_completion_matches(text, my_generator)
It obviously throws an error: call to non-static member function without an object argument but I don't want to make the generator static and I can't find what arguments it should take, because I won't be able to access class members inside of it (I need keywordlist to generate keywords).
What would you suggest?
It's not easy to solve this one in a good way, since the normal solution is to solve it by having a static wrapper function where you pass the pointer to the class in as an argument.
Someone else may be able to come up with something better, but I think the solution is to have a global variable that is a pointer to the current ReadLine class instance - this could be a stack, so you can push a new one onto it, and then pop it to get back to the old one when that's done.
In the simple case, you'd have something like this:
ReadLine *currenReadLine = 0;
....
std::string ReadLine::exec(){
...
currentReadLine = this;
}
// declared as static in the class.
char ** ReadLine::my_completion(...)
{
return currentReadLine->actual_completion(...);
}
And a similar solution for the my_generator.

Is it possible to pass a variable out of a class without creating a new object in C++

I have a variable, which is a member of one of my classes, that another is in need of, but I'm not sure how to effectively pass the value between them without using a global variable, which is something I'd like to avoid if at all possible. I know I could create an object, but that would invoke the constructor of the originating class which would execute a number of functions and write the needless results to memory, which would be wasteful of system resources.
Is there an easy way to pass this value between the two functions?
Update: The class that is in need of the variable, called no_of_existing_devices. The purpose of class Initialise is to open up a file and count the number of lines of test it contains, and place that number in the variable int no_of_existing_devices, which is then used by the Device::Device() to create an object for each
class Device
{
public:
void view_attribute_list();
void set_attribute();
Device();
};
Device::Device()
{
for (int count = 0; count < no_of_existing_devices; count ++)
{
// Create an object for each iteration, up to a maximum of no_of_existing_devices
}
}
The class of which this variable is a member
class Initialise
{
public:
int no_of_existing_devices;
bool initialisation;
string existing_device_list[100];
void initialise_existing_devices();
Initialise();
};
Initialise::Initialise()
{
no_of_existing_devices = 0;
}
void Initialise::initialise_existing_devices()
{
string line;
ifstream DeviceList;
DeviceList.open("devices/device_list");
while (true)
{
getline(DeviceList, line, '\n');
if (DeviceList.eof())
{
break;
}
++ no_of_existing_devices;
}
DeviceList.close();
DeviceList.open("devices/device_list");
for (int i = 0; i < no_of_existing_devices; i ++)
{
getline(DeviceList, line, '\n');
existing_device_list[i] = line;
}
Device existing_devices[no_of_existing_devices];
!initialisation; // Existing devices are now initialised
}
Okay, from what I understand:
You don't want to have a global
You don't want to have a static
You don't want to introduce a dependency between Device and Initialise
There is one other option, assuming something owns Device and Initialise, move the no_of_existing_devices up to there, then construct both Device and Initialise with a reference to this variable...
In a similar circumstance I was just passing the pointer to the member --- I had to invoke a member function then, so it was a pointer to the member function, http://www.parashift.com/c++-faq-lite/pointers-to-members.html
It's a bit messy, but it works :-).
If the variable in the originating class can hold a value without an instance of the class I would assume that the variable is static. If not create a public static member of the class. And use it in the target class.
Something like:
// .h file
class A
{
public:
static int a;
}
// .cpp file
int A::a = 123;
// .cpp file of class B
void B::foo()
{
cout << A::a;
}
If it is a class attribute (internal variable), then you can obtain a reference through a get method. Otherwise, you can use the friend keyword on the class you want to access the attribtue from the other For example, if you declare friend class B; on class A, the attributes of the class B will be accessible on the class A.
I suggest you use the first method in order to maintain your code OO pure ;)
Edit: of course, if you access through a reference there are no resources wasted :)
Edit 2: use a static method on Initialise class that returns the no_of_existing_devices and call Initialise::NoOfExistingDevices() on the Device class. If you want to resources use a pointer like this:
public static int* Initialise::NoOfExistingDevices() {
return &no_of_existing_devices;
}
By the way, I advise you to turn the variable private.