Callback 함수 사용에 대해 여쭈어 봅니다.

fusilier의 이미지

안녕하세요. 수고가 많으십니다.
다름이아니라 코딩 중 이해가 안되는 부분이 있어서 여쭈어 보고자 합니다.

현재 Callback 함수를 이용한 기능을 구현 중에 있는데요.
Callback이 제대로 작동되질 않아 애를 먹고 있습니다;

구체적인 내용은 다음과 같습니다.

typedef void(*CallBackFuncT)(int len, char *Data);
 
bool TestClass::GetCallbackFunc( CallBackFuncT Caller )
{
	// CallBackFuncT의 Validation 검사.
	if( NULL == Caller )
	{
		return false;
	}
 
	// Out Parameter로 전달한다. 
	Caller = ( CallBackFuncT ) PutData; 
 
	return true;
}
 
void TestClass::PutData( int nLen, char *pData )
{
	// Do Something.
}

TEST( GET_CALLBACK_FUNC_SD_TEST )
{
	CallBackFuncT Caller;
	CHECK( TestClass::GetInstance()->GetCallbackFunc( Caller ) );
	Caller( 4, "TEST" );
}

위와 같습니다. TestClass는 SingleTon 패턴으로 구현되어 있고, TEST 부분에서 하고자 하는 것은
TestClass::PutData 함수를 콜백으로 등록하여 수행하는 것입니다.

컴파일시 아래와 같은 경고가 발생하고요. 실행시키면 아무 반응이 나타나질 않습니다.

main.cpp:73: warning: deprecated conversion from string constant to 'char*'
main.cpp:73: warning: 'Caller' is used uninitialized in this function

C++ 입문단계인지라 이해하면서 코딩하려니 꽤나 힘이 드네요..
사수 분께 여쭤보아도 '맞는 것 같은데 이상하네...'란 반응 뿐.. 난감합니다;
혹시 위 내용에 대해 아시는 분은 도움 주시면 감사하겠습니다 :)

그럼 수고하시고, 좋은 하루 되세요^

cppig1995의 이미지

함수 포인터를 수정하려면 함수 포인터의 포인터를 넘겨받아야겠죠?
이해가 잘 안 되신다면 이걸 참고해 보세요.

#include <stdio.h>
 
void foo(int *p)
{
	static int a;
	p = &a;
}
 
void bar(int **pp)
{
	static int a;
	*pp = &a;
}
 
int main()
{
	int a;
	int *p = &a;
	printf("%p\n", p);
	foo(p);
	printf("%p\n", p);
	bar(&p);
	printf("%p\n", p);
}

포인터를 수정하려면 포인터의 포인터를 넘겨받아야 한다는 걸...

그나저나 문자열 리터럴, 또는 문자열 상수는 말 그대로 상수입니다. 상수성(constness)이 없는 char *가 아닙니다.
경고는 그래서 난 게 아닐까요?
--
임수서룬뫼 윤희수 {cppig1995/돼지군}

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

pizza1977의 이미지

멤버 함수를 Callback을 통해 넘기는 방법이 이렇게 간단하게 되나요?

포탈이는 불사신

-------------
포탈이는 불사신

winner의 이미지

내용이 다루고 있는 심오함은 장난이 아닌 듯... ^_^

brucewang의 이미지

우선 '임수서룬뫼' 님이 조언하신 대로 이중 포인터를 사용하셔야 되겠군요.

한가지 덧붙이자면, 어떤 클래스의 member function 을 callback 으로서 사용하시려면
그 member function 은 static 으로 하시는것이 좋다고 봅니다.

해당 callback을 사용하는 부분이 그 callback function이 정의된 클래스 인스턴스 내부에서만 사용된다면야 아무 문제가 없지만, 대부분 callback은 다른 클래스, 혹은 다른 인스턴스들(위와같은 singletone의 경우가 아니라, 하나의 클래스에서 여러개의 인스턴스가 생긴 경우) 사이에서 어떤 이벤트 전송을 위한 목적이 대부분이기때문이죠.

한가지 주의할 점은 static member function은 this pointer를 사용할 수 없기때문에, 아규먼트로 특정 인스턴스에 대한 포인터를 전달해 주시면 더욱 좋습니다.

-------------------------------------------------
$yes 4 8 15 16 23 42

codepage의 이미지

static void MyClass::MyCallBackHandler(some_args...)
{
}

반드시 static으로 선언해줘야 합니다.
왜냐하면 함수를 가리키는 포인터로 넘겨야 하는데 그럴려면 메모리에 함수의 주소가 할당되어 있어야 합니다.
static으로 선언하지 않고 return this->MyCallBackHandler; 하면 데이타 형도 맞지 않을 뿐더러(보통 컴파일할 때 에러 날 것입니다.)
넘어간다 하더라도 프로그램이 정상 동작하기를 기대할 수 없습니다.

그러면 class가 여러개라서 각각의 callBack을 호출할 경우에는 어떻게 하냐구요?

static void MyClass::MyCallBackHandler(MyClass* self, some_args...)
{
self->MyCallBackImpl(some_args...);
}

이런 식으로 하면 됩니다.

fusilier의 이미지

안녕하세요. 먼저 여러 답글 정말 감사합니다.
제가 실수를 좀 한듯한데요..;

현재 TestClass에서의 Callback함수는 다음과 같이 static으로 선언되어 있는 상태입니다;

static void PutData( int nLen, void *Data );	// Data를 받아올 Callback 함수.

위와 같은 상태이고요. 결론적으로 어제 늦게까지 남아서 해결은 보았습니다 ^^
문제는 해결은 했는데.. 왜 이렇게 써야 하는지 이해가 안되네요;;
아직 정리가 덜 된 상태라.. 좀 더 정리가 되는대로 어느 부분이 문제였는지 짚어보도록 하겠습니다.

그럼 수고하시고, 좋은 하루 되세요 :)

brucewang의 이미지

아 예, 그러셨군요. 이미 static으로 되어 있었군요.

함수의 파라미터를 char*에서 void*로 바꾸니 문제가 해결되었다는 말씀은 전에 말씀하신 컴파일시 아래의 경고가 사라졌다는 것이지요?

Quote:
main.cpp:73: warning: deprecated conversion from string constant to 'char*'

이것은 제일 첫 댓글에서 언급된 내용이었고, callback이 호출안되던 것도 이중 포인터로 제대로 함수 포인터를 전달하심으로써 모두 해결 되었다는 말씀으로 이해 해도 될런지요?

아무튼 잘 되었네요..

-------------------------------------------------
$yes 4 8 15 16 23 42

-------------------------------------------------
$yes 4 8 15 16 23 42

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.