面白いかと思ったけどツマらなかった。そもそもスクリプト言語でコンパイル言語のクラスを継承してそれをまたコンパイル言語側で使いたいこととかあるはずない。そしてコンパイラの情報使わんとロクなことできない。
ていうかまだ _ZN1C3addEii とか残ってる時点で論外。まぁ仮想関数テーブルの位置わかったしいいか…
#include <stdio.h>
#include <sys/mman.h>
#include <limits.h>
#ifndef PAGESIZE
# define PAGESIZE 4096
# define PAGESIZEMM (PAGESIZE-1)
#endif
/* 継承装置 */
void inheriter_override(void* p, void* oldfn, void* newfn) {
void** tbl = *(void***)p;
mprotect((void*)(((int)tbl+PAGESIZEMM) & ~PAGESIZEMM - PAGESIZE),
PAGESIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
while (*tbl != oldfn) tbl++;
*tbl = newfn;
}
void* inheriter_member(void* p, int i) {
return ((int*)p+1+i);
}
/* ベースクラス C */
class C {
public:
void set(int v0) { v = v0; }
virtual int add(int x, int y) { return v+x+y; }
private:
int v;
};
/* class E を作って C::add をオーバーライドする */
/* うまく消せんかった */
extern "C" {
int _ZN1C3addEii(C* c, int x, int y);
}
int E_add(C* c, int x, int y) {
int* vp = (int*)inheriter_member(c, 0);
(*vp)++;
return _ZN1C3addEii(c, x, y);
}
C* E_new() {
C* c = new C();
inheriter_override(c, (void*)_ZN1C3addEii, (void*)E_add);
return c;
}
/* 使ってみる */
int main() {
C* c = E_new();
c->set(1);
printf("%d\n", c->add(2, 3));
printf("%d\n", c->add(2, 3));
return 0;
}