5

asmブロックを介してC++メンバー関数を呼び出したい。コンパイラはMSVC++(VS2008)であり、移植性は問題ではありません。組み込みシステム用のリモーティング/RMIタイプのメカニズムを構築する必要があります。クライアントはオブジェクト名、メソッド名、arguments(serialized)を送信し、適切なオブジェクトに対してメソッドを呼び出す必要があります。PDBファイルから取得できるタイプ情報。一般的なInvoke関数を作成する必要があります。オブジェクトを引数として取るメンバー関数を呼び出す方法に固執しています。具体的には。ctorをコピーするためのポインターを取得できません。何か案が。

PS:以下のコードは、C::funcRefに対して正しくコンパイルおよび実行されます。

#include <stdio.h>
struct Point
{
   int x;
   int y;
   Point() 
   { 
       x = 10; 
       y =10;
   }
   Point(const Point& p)
   {
       x = p.x;
       y = p.y;
   }
   virtual ~Point() 
   {
   }
};

class C
{
 public:
     void funcRef(Point& p) 
     { 
         printf("C::funcRef\n x= %d, y =%d\n", p.x, p.y);
     }
     void funcObj(Point p) 
     { 
         printf("C::funcObj\nx = %d y = %d\n", p.x, p.y); 

      }

};




void main()
{
   C* c = new C;
   Point p;



   //c->funcRef(p);
   // this works
   __asm
   {

      lea eax, p;
      push eax; 
      mov ecx, c;
      call [C::funcRef];

   }

  // c->funcObj(p); 
   __asm 
   {
       sub esp, 12; // make room for sizeof(Point)
       mov ecx, esp; 
       lea eax, p;
       push eax;
       // how to call copy ctor here
       mov ecx, c;
       call [C::funcObj];

   }

}
4

2 に答える 2

2

コピーコンストラクターは非仮想であるため、名前で検索して呼び出すだけです。コンパイラがコンストラクタをコピーする方法と、シンボルを名前で解決する方法を確認してください(GetProcAddressに興味があるかもしれません)。

これはLinuxの例ですが、VisualStudioとは異なる呼び出し規約を使用していることに注意してください。

#include <stdio.h>
#include <dlfcn.h>

struct Point
{
   int x;
   int y;
   Point()
   {
       printf("Default constructing point @%p\n", this);
       x = 10;
       y = 10;
   }
   Point(const Point& p) __attribute__((used, visibility("default")))
   {
       printf("Copy constructing point @%p from point @%p\n", this, &p);
       x = p.x;
       y = p.y;
   }
   virtual ~Point()
   {
       printf("Point @%p destroyed\n", this);
   }
};

class C
{
 public:
     void funcRef(Point& p)
     {
         printf("C::funcRef\n x= %d, y =%d\n", p.x, p.y);
     }
     void funcObj(Point p)
     {
         printf("C::funcObj p = %p, x = %d, y = %d\n", &p, p.x, p.y);

      }

};

typedef void (C::*FRef)(Point&);
typedef void (C::*FObj)(Point);

int main()
{
   C* c = new C;
   Point p;

   FRef _fref =  &C::funcRef;
   FObj _fobj =  &C::funcObj;

//   c->funcObj(p);
   void* self = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
   printf("Module handle for self is %p\n", self);
   // mangled name of Point::Point(const Point&)
   void* constructor = dlsym(self, "_ZN5PointC1ERKS_");
   printf("Constructor address is %p\n", constructor);
   void* dummy;
   __asm__ __volatile__ (
      "sub esp, 32\n\t"
      "mov [esp+4], %[p] # argument to copy constructor\n\t"
      "lea eax, [esp+20]\n\t"
      "mov [esp], eax # this pointer\n\t"
      "call %[constructor] # construct instance at [esp+20]\n\t"
      "lea eax, [esp+20]\n\t"
      "mov [esp+4], eax # argument to function\n\t"
      "mov [esp], %[c] # this pointer\n\t"
      "call %[fobj]\n\t"
      "lea eax, [esp+20]\n\t"
      "mov [esp], eax # this pointer\n\t"
      "mov eax, [eax] # vtable\n\t"
      "call [eax] # destructor\n\t"
      "add esp, 32 # free rest of stack\n\t"
      : "=a" (dummy), "=c" (dummy)
      : [p] "a" (&p), [c] "S" (&c), [fobj] "D" ((void*)_fobj), [constructor] "c" (constructor)
      : "edx");
   return 0;
}

テスト走行:

Default constructing point @0xffc145e4
Module handle for self is 0xf77fb900
Constructor address is 0x8048c02
Copy constructing point @0xffc145b4 from point @0xffc145e4
C::funcObj p = 0xffc145b4, x = 10, y = 10
Point @0xffc145b4 destroyed
Point @0xffc145e4 destroyed
于 2013-01-15T23:46:05.857 に答える
0

Jesterは、この問題を解決する1つの方法を提供しました。MSVCに固有の別の方法を見つけました。FUNCDNAMEを使用して、コピーコンストラクターの装飾された名前を取得してから、procaddersを取得できます。これが私の変更したコードです

#include <stdio.h>
struct Point
{
   static char* pointCopyCtorName;
   int x;
   int y;
   Point() 
   { 
       if ( !pointCopyCtorName )
       {
           // force copy ctor
           Point(*this);
       }
       x = 10; 
       y =10;
   }
   __declspec(dllexport) Point(const Point& p)
   {
       if ( !pointCopyCtorName )
         pointCopyCtorName = __FUNCDNAME__;
       if ( this != &p )
       {
            x = p.x;
            y = p.y;
       }
   }

   virtual ~Point() 
   {
   }
};
char* Point::pointCopyCtorName = NULL;



class C
{
 public:
     void funcRef(Point& p) 
     { 
         printf("C::funcRef\n x= %d, y =%d\n", p.x, p.y);
     }
     void funcObj(Point p) 
     { 
         printf("C::funcObj\nx = %d y = %d\n", p.x, p.y); 

      }

};


HMODULE GetCurrentModule()
{
    HMODULE hMod = NULL;
    GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, 
        (LPCTSTR) "GetCurrrentModule", &hMod);
    return hMod;
}


void main()
{
   C* c = new C;
   Point p;
   HMODULE hMod = GetCurrentModule();
   if ( !hMod )
       return;

   FARPROC pPointCopyCtor = GetProcAddress(hMod, p.pointCopyCtorName);
   if ( !pPointCopyCtor )
       return;


   //c->funcRef(p);
   // this works
   __asm
   {

      lea eax, p;
      push eax; 
      mov ecx, c;
      call [C::funcRef]; 
   }

  // c->funcObj(p); 
   __asm 
   {
       sub esp, 12;
       mov ecx, esp;
       lea eax, p;
       push eax;
       call pPointCopyCtor;
       mov ecx, c;
       call [C::funcObj];
   }

}
于 2013-01-16T15:13:25.193 に答える