Jump to page: 1 2
Thread overview
Pointer to method C++ style
Jul 23, 2009
Sergey Gromov
Jul 23, 2009
BCS
Jul 23, 2009
Sergey Gromov
Jul 23, 2009
BLS
Jul 23, 2009
Sergey Gromov
Jul 23, 2009
BLS
Jul 23, 2009
Sergey Gromov
Jul 24, 2009
Sergey Gromov
Jul 24, 2009
Sergey Gromov
Jul 24, 2009
grauzone
Jul 24, 2009
Sergey Gromov
July 23, 2009
Is there a way to declare and statically initialize some sort of pointer to method, and later call it for an actual object instance?

Use case: I'm writing an ActiveX plug-in for a dynamic language.  The language queries the component for implemented methods, then it requests these methods to be executed.  I want to implement these methods as the component class non-static members, and create a lookup table at compile time, sort of

struct Method
{
    string name;
    PointerToMember method;  // some magic goes here
}

class Component : IUnknown
{
    void method1() {}
    void method2() {}

    static Method[] LOOKUP_TABLE =
    [
        { "method1", &method1 },  // won't work, &method1 is non-const
        { "method2", &method2 }
    ];

    void call(int i)
    {
        this->*LOOKUP_TABLE[i].method(); // sort of
    }
}
July 23, 2009
Hello Sergey,

> Is there a way to declare and statically initialize some sort of
> pointer to method, and later call it for an actual object instance?
> 

dosn't work but might point you in the right direction:

template Pn2Fn(R, char[] method)
{
    ReturnTypeOf!(mixin("R." ~ method)) Pn2Fn(R r, ArgsOf!(mixin("R." ~ method)) args)
    {
         return mixin("r."~method~"(args);");
    }

}


// use

auto it = &Pn2Fn!(Type, "method");

//call as

it(type);


July 23, 2009
Sergey Gromov wrote:
> Use case: I'm writing an ActiveX plug-in for a dynamic language.  The

> class Component : IUnknown

WOW!

But shouldn't you use

class Component : IDispatch
{
  HRESULT QueryInterface( REFIID riid, LPVOID * ppvObj) {};
  ULONG   AddRef() {};
  ULONG   Release(){};

  // plus IDispatch methods
  // GetTypeInfoCount, GetTypeInfo, GetIDsOfNames, Invoke.
  // to support late binding ?
}

instead ?

Beside, John C. (Juno library) is a specialist (guru) regarding this topic. maybe he is willing to help.

However, I am _very_ interested in having/seeing the source of a very basic ActiveX control. Any chance that you share the core implementation with us ?
björn


July 23, 2009
Thu, 23 Jul 2009 12:37:42 +0200, BLS wrote:

>Sergey Gromov wrote:
>> Use case: I'm writing an ActiveX plug-in for a dynamic language.  The
>
> However, I am _very_ interested in having/seeing the source of a very basic ActiveX control. Any chance that you share the core implementation with us ?

Sorry, I'm not a guru at all, so ActiveX was a misnomer.  What I'm writing is a simple in-process server DLL which implements a couple of interfaces.
July 23, 2009
Thu, 23 Jul 2009 04:11:14 +0000 (UTC), BCS wrote:

> Hello Sergey,
> 
>> Is there a way to declare and statically initialize some sort of pointer to method, and later call it for an actual object instance?
>> 
> 
> dosn't work but might point you in the right direction:
> 
> template Pn2Fn(R, char[] method)
> {
>      ReturnTypeOf!(mixin("R." ~ method)) Pn2Fn(R r, ArgsOf!(mixin("R." ~
> method)) args)
>      {
>           return mixin("r."~method~"(args);");
>      }
> 
> }

Thanks for the advice.  The following code actually works:

import std.stdio;

struct Handler(T)
{
  string name;
  void function(T instance) handler;
}

class A
{
  void method1() { writefln("method1"); }
  void method2() { writefln("method2"); }

  void call(int i)
  {
    LOOKUP_TABLE[i].handler(this);
  }

private:

  static Handler!(A)[] LOOKUP_TABLE =
  [
    { "method1", &callMethod!("method1") },
    { "method2", &callMethod!("method2") }
  ];

  static void callMethod(string name)(A instance)
  {
    mixin("instance." ~ name ~ "();");
  }
}

void main()
{
  A a = new A;
  a.call(0);
  a.call(1);
}
July 23, 2009
On Wed, 22 Jul 2009 23:47:30 -0400, Sergey Gromov <snake.scaly@gmail.com> wrote:

> Is there a way to declare and statically initialize some sort of pointer
> to method, and later call it for an actual object instance?

I don't know why the "non constant expression error" happens, but constructing a delegate from function pointers is pretty simple:

import tango.io.Stdout;

struct Method
{
    char[] name;
    void function() method;
}

class Component
{
    void method1() {Stdout("method1").newline;}
    void method2() {Stdout("method2").newline;}


    // this works, but not sure why I couldn't initialize via a simple array assign...
    static Method[] LOOKUP_TABLE;
    static this()
    {
        LOOKUP_TABLE = new Method[2];
        LOOKUP_TABLE[0] = Method("method1", &Component.method1);
        LOOKUP_TABLE[1] = Method("method2", &Component.method2);
    }

    void call(int i)
    {
        // construct a delegate to call
        void delegate() dg;
        dg.ptr = cast(void*)this;
        dg.funcptr = LOOKUP_TABLE[i].method;
        // call the delegate
        dg();
    }
}

void main()
{
    Component a = new Component;
    a.call(0);
    a.call(1);
}

-------
outputs:

method1
method2

-Steve
July 23, 2009
Sergey Gromov wrote:
> Thu, 23 Jul 2009 12:37:42 +0200, BLS wrote:
> 

> Sorry, I'm not a guru at all, so ActiveX was a misnomer.  What I'm
> writing is a simple in-process server DLL which implements a couple of
> interfaces.

Oh, that's sad. :(

well, especially in this case I would suggest to have a look on this page :
http://www.dsource.org/projects/juno/wiki/ComProgramming

--- I think John's juno.com.server module contains almost everything you need.

good luck











July 23, 2009
Thu, 23 Jul 2009 19:07:43 +0200, BLS wrote:

> Sergey Gromov wrote:
>> Sorry, I'm not a guru at all, so ActiveX was a misnomer.  What I'm writing is a simple in-process server DLL which implements a couple of interfaces.
> 
> Oh, that's sad. :(
> 
> well, especially in this case I would suggest to have a look on this page : http://www.dsource.org/projects/juno/wiki/ComProgramming

Thanks, I'll look into it when I have time.
July 24, 2009
Thu, 23 Jul 2009 11:54:40 -0400, Steven Schveighoffer wrote:

> On Wed, 22 Jul 2009 23:47:30 -0400, Sergey Gromov <snake.scaly@gmail.com> wrote:
> 
>> Is there a way to declare and statically initialize some sort of pointer to method, and later call it for an actual object instance?
> 
> I don't know why the "non constant expression error" happens, but constructing a delegate from function pointers is pretty simple:

It's my understanding that you cannot construct a delegate from a function pointer because they use different calling conventions.  Though you show here that it *is* possible to construct a delegate from another delegate you dissected earlier.

>          LOOKUP_TABLE[0] = Method("method1", &Component.method1);
>          LOOKUP_TABLE[1] = Method("method2", &Component.method2);

These two lines are weird.  ``pragma(msg)`` shows that type of ``&method1`` is ``void function()`` while it must be ``void delegate()`` for a non-static member because of difference in calling convention. Actually I think that taking an address of a non-static member in a static context must be a compile time error.
July 24, 2009
On Thu, 23 Jul 2009 22:09:12 -0400, Sergey Gromov <snake.scaly@gmail.com> wrote:

> Thu, 23 Jul 2009 11:54:40 -0400, Steven Schveighoffer wrote:
>
>> On Wed, 22 Jul 2009 23:47:30 -0400, Sergey Gromov <snake.scaly@gmail.com>
>> wrote:
>>
>>> Is there a way to declare and statically initialize some sort of pointer
>>> to method, and later call it for an actual object instance?
>>
>> I don't know why the "non constant expression error" happens, but
>> constructing a delegate from function pointers is pretty simple:
>
> It's my understanding that you cannot construct a delegate from a
> function pointer because they use different calling conventions.  Though
> you show here that it *is* possible to construct a delegate from another
> delegate you dissected earlier.
>
>>          LOOKUP_TABLE[0] = Method("method1", &Component.method1);
>>          LOOKUP_TABLE[1] = Method("method2", &Component.method2);
>
> These two lines are weird.  ``pragma(msg)`` shows that type of
> ``&method1`` is ``void function()`` while it must be ``void delegate()``
> for a non-static member because of difference in calling convention.
> Actually I think that taking an address of a non-static member in a
> static context must be a compile time error.

It's because I'm taking the address of the function on the type, not on an instance.  It's not a delegate because there's no "this" pointer yet.

It makes sense to me anyways.  A delegate is a normal function pointer coupled with a hidden context parameter.

I think it should be possible to construct the table statically, since the functions exist statically (without 'this' pointers).  Either I can't find the right syntax, or it is a bug.

-Steve
« First   ‹ Prev
1 2