c에서 cpp 클래스 멤버 함수 호출에 관하여

cho's의 이미지

현재 c에서 cpp의 클래스 호출하려고 합니다.
형식은 다음과 같이 클래스 object를 가지고 와서 그 멤버 함수를 호출하려고 합니다. 세그멘트 에러가 나는데 이유를 잘 모르겠습니다.
어셈블 코드를 봐도 크게 틀린것 같지는 않은데요. 어떻게 해야 할까요?
그냥 멤버함수가 아닌형태로 하면 되긴 하지만 꼭 이렇게 해야만 될 이유가 있어서요.
t1.c

#include <stdio.h>

typedef struct _XX {
	void (*ftn3)(void*);
	int (*ftn4)(void*, int,int);
} XX;

void* get_ptr(void);

int main(int argc, char* argv[])
{
	XX* p = (XX*)get_ptr();
	p->ftn3(p);
	p->ftn4(p, 10,11);
}

t2.cc
#include <stdio.h>

class X {
public:
	int x;
	int y;
	static void ftn1(void);
	static int ftn2(int,int);
};

void (X::*ftn1)(void);
void (X::*ftn2)(int, int);


void X::ftn1(void)
{
	printf("X::ftn1.\n");
}
int X::ftn2(int x1,int y1)
{
	int a,b;
	int a1,b1;
	int a2,b2;
	printf("X::ftn2.(%d,%d)\n",x1,y1);
	a=9;b=10;
	a1=91;b1=101;
	a2=92;b2=102;
	//x=77;y=88;
}

X x0;
extern "C" void* get_ptr(void)
{
	//int* p= (int*)&x0;
//printf("(%x,%x,%x,%x)\n",*p,*(p+1),*(p+2),*(p+3));
	return (void*)(&x0);

t1.c를 어셈블 코드로 변환했을때 모습입니다. 이코드를 기준으로 살펴보고 있는데 클래스 오브젝을 받아서는 이상이 없고 이 받은것을 this처럼 넘기는데 제대로 된것 같거든요. 어셈 코드를 기준으로 자세히 설명해 주신다면 고맙겠습니다.
t1.s

main:
	pushl	%ebp
	movl	%esp, %ebp //stack frame을 ebp에 세팅
	subl	$8, %esp // 8byte를 확보한다는 얘긴가요?
	andl	$-16, %esp // -16을 더하면 어떻게 되나요?
	movl	$0, %eax // eax를 초기화하는 건가요?
	subl	%eax, %esp 
	call	get_ptr
	movl	%eax, -4(%ebp) // -4는 첫번째 지역번수 즉 class p를 가지고 온것
	subl	$12, %esp // 12byte를 어떻게 확보한다는 얘긴가요?
	movl	-4(%ebp), %eax 
	pushl	-4(%ebp)
	movl	(%eax), %eax
	call	*%eax // 이 부분이 잘못된것 같습니다. 그냥 클래스를 부르는것 같습니다.어떻게 해야 할까요?
	addl	$16, %esp
	subl	$4, %esp
	movl	-4(%ebp), %eax
	pushl	$11
	pushl	$10
	pushl	-4(%ebp)
	movl	4(%eax), %eax
	call	*%eax
	addl	$16, %esp
	leave
	ret

상세하게 알고싶습니다. 솔직히 잘 이해가 안되거든요.
좋은 하루 되십시오.

pynoos의 이미지

get_ptr 이 마치 생성자의 역할을 해야하는데, 그렇지 않은 코드이군요.

C++ member 함수를 호출할 때는, C++ 에서 (C아닌) wrapper 함수를 제공해주어야 정상적으로 호출할 수 있습니다.

심지어 위의 코드에서 X::ftn1, X::ftn2 함수는 static 이므로 this pointer가 넘어가지 않는 함수이군요.

어셈블 코드를 설명하는 방식이 아니어서 죄송합니다만. 위에 제시하신 class X를 C 코드에서 사용하려면, 다음과 같은 interface를 작성해주시는 것이 좋습니다. ftn1과 ftn2 를 static 으로 하지 않는 코드로 설명드리면..

t2.cc

class X { 
public: 
   int x; 
   int y; 
   void ftn1(void); 
   int ftn2(int,int); 
}; 

type void XX;

extern "C" XX * X_init()
{
        return (XX *) new X;
}

extern "C" void X_ftn1( XX * pthis )
{
        ((X*)pthis)->ftn1();
}

extern "C" int X_ftn2( XX * pthis, int a, int b )
{
       return ((X*)pthis)->ftn2(a,b);
}

extern "C" void X_destroy( XX * pthis )
{
        delete pthis;
}

t1.c

int main(int argc, char* argv[]) 
{ 
   XX * p = X_init(); 
   X_ftn1(p); 
   X_ftn2(p,10,11);
   X_destroy( p );
} 

... 컴파일 안하고 올리는거라 오류가 있다면 답글 주세요. 메모리 할당 오류 등은 생략하였습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.