[omniORB] Is this doable

Bruce Visscher bvisscher@mindspring.com
Wed, 10 Mar 1999 22:41:19 -0500


IMHO, this is more of a general C++ question than omniORB or even CORBA specific.

In any case,

Bing Zhang wrote:

> Hi,
>
> I modified a little bit of echo example to as following:
>
> class Echo_i : public virtual _sk_Echo {
> public:
>   Echo_i() {}
>   virtual ~Echo_i() {}
>   virtual char * echoString(const char *mesg);  //defined in idl
>   virtual void testit();  // not defined in idl
> };
> void Echo_i::testit() {
>         cerr << "Sleeping  -----" << endl;
>         Sleep(10000);
>   }
>
> typedef void (Echo_i::*SpMType1)();
>
> struct CTstruct {
>     SpMType M;

I thinks this must have been SpMType1 originally.

>
>         Echo_i* O;
> };
>
> void SpMWrapper(void* pCTparam) {
>     Echo_i* my_O = ((CTstruct*)pCTparam)->O;
>     SpMType1 my_M = ((CTstruct*)pCTparam)->M;
>
>     while(true) {
>         (my_O->*my_M)();
>     }
> }
>
> int main(int argc, char **argv)
> {
>   CORBA::ORB_ptr orb = CORBA::ORB_init(argc,argv,"omniORB2");
>   CORBA::BOA_ptr boa = orb->BOA_init(argc,argv,"omniORB2_BOA");
>
>   struct CTstruct par;
>   Echo_i *myobj = new Echo_i();
>   par.O = myobj;
>   par.M = Echo_i::testit;
>   DWORD TID_TMOM;
>   HANDLE hThread_TMOM = CreateThread(NULL,
>                                                                 0,
>                                                                 (LPTHREAD_START_ROUTINE)SpMWrapper,
>                                                                 &par,
>                                                                 0,
>                                                                 (LPDWORD)&TID_TMOM
>                                                                 );
>     if(hThread_TMOM == NULL) {
>                 cerr << "TMOM thread cannot be created\n";
>         }
> }
>
> Everything works fine. method testit() in future will be used to
> perodically update a CORBA object internal state.
>
> Now we want to enable the thread to run any CORBA object's member method (
> as long as the member method do not return anytion and take no parameters),
> we modify part of the code as
>
> typedef void (CORBA::Object::*SpMType)();
>
> struct CTstruct {
>     SpMType M;
>         CORBA::Object* O;
> };
>
> void SpMWrapper(void* pCTparam) {
>     CORBA::Object* my_O = ((CTstruct*)pCTparam)->O;
>     SpMType my_M = ((CTstruct*)pCTparam)->M;
>
>     while(true) {
>         (my_O->*my_M)();
>     }
> }
>
> The main function is same. But the compiler complains the statement:
> par.M = Echo_i::testit;
> error C2440: '=' : cannot convert from 'void (Echo_i::*)(void)' to 'void
> (CORBA::Object::*)(void)'
>                                    Types pointed to are unrelated;
> conversion requires reinterpret_cast, C-style cast or function-style cast
> Error executing cl.exe.

But this is exactly right.  You cannot cast a pointer to member function of a derived class to a
pointer to member function to base.  Think about it.  All you have is a pointer to a CORBA::Object that
you are going to invoke the pointer to member function on.  You then attempt to assign the pointer to
member function from Echo_i::testit.  You have no guarantee that the object represented by the
CORBA::Object pointer has such a function (in general, it won't).

OTOH, there has been some discussion in comp.std.c++ that you might be interested in regarding
"closures" and how this might be implemented in (standard) C++ (apparently motivated by the closure
feature as implemented in Borland Builder).  Look in Dejanews for articles by Lisa Lippincott and
Andrei Alexandescu.  Lisa and Andrei came up with an implementation of pretty much exactly what you are
trying to do in a typesafe, generic way.  Unfortunately, the solution requires an advanced compiler
(not sure if MSC is up to it: haven't tried it myself).

Sorry for the topic drift.

HTH,

Bruce