Click here to Skip to main content
15,886,763 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Suppose I have a print Method which takes a void* as an argument:

C++
Print(void *instance)


How can I Set the member of a struct to this method?

C++
struct Foo
    {
        void(*Print)(); //this does not match to Print above!
       //void(*Print)(void* Instance); //This would but I cannot change this
    }


So how would I have to change this method:
C++
void Init()
{
   struct Foo* k = malloc(sizeof(Foo));

   Foo->Print = &Print(k);   //does not work!
 //Foo->Pring = &Print;     //would work if types were the same and I really need the parameter k there.
    }


I want to set a function pointer with a Fixed Argument.
This would be to make truly object like behaviour in ANSI C for this Project:
Object Orientation in C?!

String* r = New_String("Hello");
r->Free(r);
Should become r->Free();

Thanks in advance

What I have tried:

Other languages would support it like this:

Foo.Print = ()=>Print(k);

The argument has to be inserted at runtime.
Any non standard crazy ways are appreciated.

For example finding the Foo struct instance from the method which was used to call Foo->Print();
Posted
Updated 3-Oct-16 9:31am
v3
Comments
Philippe Mori 7-Oct-16 13:32pm    
Tell us why you don't use a C++ compiler if you want to use C++ syntax.
Philippe Mori 7-Oct-16 13:43pm    
Also give us links to other forum where someone told you it can be done with "memory access callback".

The function signature must match, otherwise you could have something like:
C++
void Print(void* pp)
{
	// do stuff
}
void Print(char* cp, int i)
{
	// do stuff
}

//

struct Foo
{
    void(*Print)(); // so which one does the compiler choose?
}
 
Share this answer
 
Comments
D. Infuehr 3-Oct-16 15:28pm    
The compiler cant choose because it complains that no overload is suitable.
My question is about how to Pass the Function around with a single Parameter (of the function) set to a specific value.
I have changed my question to clarify.
Richard MacCutchan 4-Oct-16 4:05am    
What you want to do is not possible in C/C++. You must follow the rules of the language.
There are no easy way to do that in C. Of course, you could write assembler code to dynamically create a function with specified argument (assuming you are allowed to write such code in your developing environment).

On the other hand, you probably don't really need that. Usually, you would have a static function taking instance argument in your struct and that function would call member function of that instance.

It is not clear if you are writing C or C++ code. If you write C code, then you don't have member function anyway so it is pointless to do that kind of stuff. If you write C++ code, then you should have used new instead of malloc anyway...

Also, it look weird that you want to set a function pointer in a struct point to a global function.

Obviously, it that is what you want to do, then it is extremely simple (assuming C++):
C++
struct Foo
{
    void(*Print)(void* Instance);
    void PrintMe() { (*Print)(this); }
};

If you really want to it the other way, then you would have a static member taking a parameter that would be interpreted as an instance:
C++
struct Foo2
{
    static void PrintFuction(void *instance) 
    { 
        reinterpret_cast<foo2>(instance)->PrintMember();
    }
    static void PrintMember() { /* code here */ }
};


By the way, in other language as C#, the compiler would essentially generate a class with the data in the members of it. And such function would be represented by a pair of {function, instance}.

Also, in modern C++ you also have such function object.

Thus it is not clear what you are trying to achieve with that and it might not be the best way to do it... in particular if you have access to the whole code.

— Update (2016-10-07)—

As indicated in comments, it is not possible to achieve desired syntax using only standard C.

For "Memory access callback", I didn't know about that. I have found the following information: http://stackoverflow.com/questions/6211429/callback-on-memory-access/6211502[^].

The thing I can say it that it is a specific Linux function. And to use it for the purpose of simplifying the syntax, one would have to ensure that he use the proper calling convention, that any used compiler optimization are compatible with the hack and that he would never want to port the code to any other platform where such hack might not be possible.

Essentially, the hack would be that in some specific cases, you might know in which register or relative stack location is the address of the function just called. From that information, you might be able to compute the address of "this" and make any necessary adjustment so that the function see the correct information.

And even then, that hacking might give you problems with debugging, error handling or compatibility issues.

This is not something that should be used for regular development or just for the convenience of a nicer syntax. If this is what you want, then you should seriously consider a C++ compiler.

That kind of hack might be useful if one develop some specific library for a specific platform for things like RTOS, profilers, stack trace analysers... But if you wrote such tools, then you need to have a deep understanding of your platform and compiler.

Seriously... uses a C++ compiler!

It does not make sense to do that kind of hack in most cases and in particular if the only purpose is to have a nicer syntax.

Obviously, there are so many reason why it might break that it won't worth the effort. In fact, if you application crash or does not behave correctly afterwards, you have no idea if the problem is caused by the hack and no easy way to test it since you would have to revert all the changes you made to improve the code.

Alternative

You can use a C++ compiler that is able to generate C code. See http://stackoverflow.com/questions/3311563/do-all-c-compilers-generate-c-code[^] for more information.
 
Share this answer
 
v5
Comments
D. Infuehr 3-Oct-16 15:30pm    
In C++ this would be trivial. I want to use C++ like syntax in C. I have altered my question to clarify.
Basically
String* r = New_String("Hello");
r->Free(r);
Should become r->Free();
so that the instance does not have to be passed to the methods themselfes.
Philippe Mori 3-Oct-16 15:51pm    
Obviously, you cannot do that in C alone. As far as I know, the only way to simulate that syntax would be to generate a proxy in assembler code but then how would you have to handle memory allocation... and other problems.

If you really want to uses C++ syntax, then uses a C++ compiler. If you cannot use a C++ on your platform (maybe some embedded device), then you might be able to find a C++ compiler that generate C code for you.

Otherwise, you would have to write your own pre compiler. This is the solution that was uses at the C++ beginning (I think it was called C++ with classes).
Philippe Mori 3-Oct-16 16:00pm    
You have to understand a bit how the code is generated. In C++, the compiler will push this on stack before calling a function. Thus C++ compiler would more or less generate code as if the function as an extra hidden argument.
Obviously, C compiler won't push that argument as that would serve no purpose in C code.
Thus any possible hack could only make things worst. You can only make the code harder to read and maintain.
D. Infuehr 7-Oct-16 11:25am    
I want to achieve C++ like syntax. The best so far is Foo->Print(Foo). I want to get Foo inside of Print without passing it as an argument explicitly.
On a Forum where people really answer the question and dont just tell me its impossible, someone has pointed out that i could write a memory access callback invoked when the Foo->Print location is accessed which pushes Foo onto the stack. Then I can call print like it is supposed to work. (like the this pointer)
Does somebody know how to do that?
Philippe Mori 7-Oct-16 13:42pm    
I have updated my answer with much more information...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900