Macros, vTable?

A

Alexander Adam

Hi!

I've got an issue. I have more or less an internal class model for
which I want to write various bindings e.g. for Windows COM. Now I've
figured to make my internal classes based on IDispatchEx which works
fine. The biggest pain I have right now is that I need to register
properties and methods dynamically and I need to call those
dynamically, too. Take the following example:

struct method {
short calltype; // 0=property_get, 1=property_set, 2=method
unsigned id;
const char* name;
int* params;
}

class A :
public MyTemplate<A>
{
public:
BEGIN_METHODS(A)
METHOD(0, "something", 1, {})
METHOD(1, "something", 2, {})
METHOD(2, "doSomething", 3, {4,5,2})
END_METHODS
public:
// Properties
virtual std::string get_Something();
virtual void set_Something(const std::string& name);

// Methods
virtual void doSomething();
}


Now in myTemplate I have two functions called from outside, one to get
an unique id for the given name and type and one for calling it. The
question I have is this:

The biggest pain is that I've wanted to call the functions that I have
registered with METHOD() macro directly, passing the parameters
dynamically as an array. But as I'd require my own call stack frame
and my asm knowledge is not the best, I've thought to create two
functions within my BEGIN_METHODS and END_METHODS macros that is, one
for registering the functions which could look like

static const method* _get_methods()
{
...
}

and one that calls it like

void _call_method(int id, params* p)
{
switch( id)
{
case 2: doSomething(p[0].int, p[1].double);
....
}


Now as you can see the issue I have is that I cannot have my Macros
declare two independant functions that is, to be able to create a
_get_methods and a _call_method routine, I'd need to redeclare
evertything like this:


class A :
public MyTemplate<A>
{
public:
BEGIN_METHODS(A) // _get_methods()
METHOD(0, "something", 1, {})
METHOD(1, "something", 2, {})
METHOD(2, "doSomething", 3, {4,5,2})
END_METHODS


BEGIN_METHODS2(A) // _call_method
METHOD(0, (p[0].int, p[1].double))
END_METHODS2
public:
// Properties
virtual std::string get_Something();
virtual void set_Something(const std::string& name);

// Methods
virtual void doSomething();
}


You might see my issue here -- I have to declare everything twice
which is not really nice.

So after fighting and trying and everything for days, I was hoping
that someone could help me out here with a smart advice, hint, help or
anything?

Thanks and Regards
Alexander
 
J

John Harrison

Alexander said:
Hi!

I've got an issue. I have more or less an internal class model for
which I want to write various bindings e.g. for Windows COM. Now I've
figured to make my internal classes based on IDispatchEx which works
fine. The biggest pain I have right now is that I need to register
properties and methods dynamically and I need to call those
dynamically, too. Take the following example:

struct method {
short calltype; // 0=property_get, 1=property_set, 2=method
unsigned id;
const char* name;
int* params;
}

class A :
public MyTemplate<A>
{
public:
BEGIN_METHODS(A)
METHOD(0, "something", 1, {})
METHOD(1, "something", 2, {})
METHOD(2, "doSomething", 3, {4,5,2})
END_METHODS
public:
// Properties
virtual std::string get_Something();
virtual void set_Something(const std::string& name);

// Methods
virtual void doSomething();
}


Now in myTemplate I have two functions called from outside, one to get
an unique id for the given name and type and one for calling it. The
question I have is this:

The biggest pain is that I've wanted to call the functions that I have
registered with METHOD() macro directly, passing the parameters
dynamically as an array. But as I'd require my own call stack frame
and my asm knowledge is not the best, I've thought to create two
functions within my BEGIN_METHODS and END_METHODS macros that is, one
for registering the functions which could look like

static const method* _get_methods()
{
...
}

and one that calls it like

void _call_method(int id, params* p)
{
switch( id)
{
case 2: doSomething(p[0].int, p[1].double);
...
}


Now as you can see the issue I have is that I cannot have my Macros
declare two independant functions that is, to be able to create a
_get_methods and a _call_method routine, I'd need to redeclare
evertything like this:


class A :
public MyTemplate<A>
{
public:
BEGIN_METHODS(A) // _get_methods()
METHOD(0, "something", 1, {})
METHOD(1, "something", 2, {})
METHOD(2, "doSomething", 3, {4,5,2})
END_METHODS


BEGIN_METHODS2(A) // _call_method
METHOD(0, (p[0].int, p[1].double))
END_METHODS2
public:
// Properties
virtual std::string get_Something();
virtual void set_Something(const std::string& name);

// Methods
virtual void doSomething();
}


You might see my issue here -- I have to declare everything twice
which is not really nice.

So after fighting and trying and everything for days, I was hoping
that someone could help me out here with a smart advice, hint, help or
anything?

Well, my honest advice would be give up and do something more productive
with your time. But I guess you don't want me to tell you that.

So.

Why not combine _get_methods and _call_method into a single function?
Any reason that can't be done? Sure it's ugly but you seem to be in ugly
territory anyway.

john
 
A

Alexander Adam

Hi,
Well, my honest advice would be give up and do something more productive
with your time. But I guess you don't want me to tell you that.

How is it you come to that opinion?
The issue here is just that the internal object model is quite huge (>
1800 classes) and I've started building COM Wrappers around each
object but it took way too much time to just implement a few classes
so I've decided to let each single class be the COM Object itself.
So.

Why not combine _get_methods and _call_method into a single function?
Any reason that can't be done? Sure it's ugly but you seem to be in ugly
territory anyway.

Uhm that's what I've tried first, too. The issue is just that I need
to register the function before using it within _call_method. This is
necessary to be able to check for parameters count, types etc. and
combining both into one function wouldn't really work in this case as
the code gets really really unusable. How's it you're saying that I
seem to be in ugly territory anyway, do you mean my C Code is ugly?
Well I've just written that as more or less pseudo code, not saying
that the original code looks as crappy as this one. Or is it that you
say calling dynamic functions is the ugly territory?

I'd be very thankful for some more hints on such kind of issue, I
can't believe I am the only one having this as calling dynamic
functions including dynamic parameters and returns seems to me as a
quite common problem?

Regards
Alexander
 
S

Stuart Redmann

Alexander said:
Hi!

I've got an issue. I have more or less an internal class model for
which I want to write various bindings e.g. for Windows COM.

If I understand you right, you have some classes written (presumably) in
C++, but you want to publish your framework via Microsoft COM to the
world. This involves a lot of work, as you can only define interfaces in
COM, whereas C++ mixes interfaces and implementation into single
entities. This means that you'll have to untangle interfaces from
implementations by hand, which is going to be quite time-consuming.
> Now I've
figured to make my internal classes based on IDispatchEx which works
fine. The biggest pain I have right now is that I need to register
properties and methods dynamically and I need to call those
dynamically, too. Take the following example:

I don't believe that working with IDispatchEx is useful here, as you'll
need to work over your code completely. So instead of doing this, you
may as well start with defining real COM interfaces and make your C++
classes to implementors of these interfaces.

IDispatchEx as COM interface doesn't make sense to me, as it is intended
for dynamically adding properties and methods to objects. Adding
properties can be done by any container class, and adding methods is not
useful (as they cannot access private data members, and that is what
half of object-orientation is all about: encapsulation).

Anyway, if you're using IDispatchEx you'll have to be automation
compatible, and I very much doubt that your C++ framework is automation
compatible. I'd advice you to start introducing real COM (not using
IDispatchEx) interfaces in your project step by step.

Regards,
Stuart
 
W

W Karas

Now as you can see the issue I have is that I cannot have my Macros
declare two independant functions that is, to be able to create a
_get_methods and a _call_method routine, I'd need to redeclare
evertything like this:

class A :
public MyTemplate<A>
{
public:
BEGIN_METHODS(A) // _get_methods()
METHOD(0, "something", 1, {})
METHOD(1, "something", 2, {})
METHOD(2, "doSomething", 3, {4,5,2})
END_METHODS

BEGIN_METHODS2(A) // _call_method
METHOD(0, (p[0].int, p[1].double))
END_METHODS2
public:
// Properties
virtual std::string get_Something();
virtual void set_Something(const std::string& name);

// Methods
virtual void doSomething();

}

You might see my issue here -- I have to declare everything twice
which is not really nice.
....

class A :
public MyTemplate<A>
{
public:
#undef L
#define L(METHOD) \
METHOD(0, "something", 1, {}) \
METHOD(1, "something", 2, {}) \
METHOD(2, "doSomething", 3, {4,5,2})

GENERATE_GET(L)

GENERATE_CALL(L)
....

On the other hand, I'm not sure I see why you
can't go with a (macro-free) solution that just
uses an array:

int doSomethingParam[] = {4,5,2};

method myMethods[] =
{
{"something", 1, 0},
{"something", 2, 0},
{"doSomething", 3, doSomethingParam}
};
 
A

Alexander Adam

hi,
class A :
public MyTemplate<A>
{
public:
#undef L
#define L(METHOD) \
METHOD(0, "something", 1, {}) \
METHOD(1, "something", 2, {}) \
METHOD(2, "doSomething", 3, {4,5,2})

GENERATE_GET(L)

GENERATE_CALL(L)
...

On the other hand, I'm not sure I see why you
can't go with a (macro-free) solution that just
uses an array:

int doSomethingParam[] = {4,5,2};

method myMethods[] =
{
{"something", 1, 0},
{"something", 2, 0},
{"doSomething", 3, doSomethingParam}

};

I would love to go with a macro free solution but the issue is exactly
what you mention here -- how tp pass the doSomethingParam over to the
dynamic function call? Because it is not one array of int but it can
be an array of different types and should go directly into the
function which could look like doSomething(int aNumber, string
aValue, ..)

Regards
Alexander
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top