함수 포인터를 (void *) 로 형변환 했다 다시 함수포인터로...

icristi의 이미지

함수 포인터를 전달받는 함수를 쓰레드로 만들고 싶어서(pthread_creadte)
함수포인터를 void * 으로 형 변환 했습니다.

다시 함수 포인터로 형변환 하는 방법이 있을까요?

bool CMainThread::Create( void* (*func)(void*) )
{
       pthread_create( &m_hThread, NULL, &CMainThread::Run, (void*)func );
.
.
.


void* CMainThread::Run( void* func )
{

     //func 를 어떻게 함수로 쓸까요?

.
.
.
}



한 가지 더요!

[root@devel dcdManager]# gcc -c MainThread.cpp
MainThread.cpp: In method `bool CMainThread::Create ()':
MainThread.cpp:42: ISO C++ forbids taking the address of an unqualified 
non-static member function to form a pointer to member function.  Say 
`&CMainThread::Run'
MainThread.cpp:42: cannot convert `void *(CMainThread::*) (void *)' to 
`void *(*) (void *)' for argument `3' to `pthread_create (pthread_t *, 
const pthread_attr_t *, void *(*) (void *), void *)'

pthread_create 에 원래 static 함수 밖에 쓰지 못하나요?
멤버 함수 &Run 을 그냥 쓰니까 저런 에러메세지가 나오네요.
static으로 바꾸니까 되긴 해요...

요즘 이것 저것 참 물어보는 것만 많네요...
KLDP에 도움이 되고자 하지만 지금 제 수준에서는 그저 이렇게
궁금증을 해소를 위한 하소연 밖에 못하네요....ㅜ.ㅜ

저도 언젠가 내공이 많이 쌓이면 왕성한~ 답변활동(?)을 통해
도움 받은 것 환원해야겠죠~~~ ^^;;[/code]

chunsj의 이미지

질문에 이미 답이 있습니다. void *(*func) (void *);
좀 멋있게 하려면,
typedef void * (*ThreadHandlerFunc) (void *);
이렇게 해서 type casting을 하면 되겠죠. 꼭 안해도 되고...
혹시나 해서 예제를 쓰면 Run에서 func이 넘어왔다면
ThreadHandlerFunc doThis = (ThreadHandlerFunc)func;
이렇게 하고 doThis((void *)&aa); 뭐 이런식으로 쓸 수 있겠죠. 그런데
꼭 이렇게 하시는 이유가 있으신지?

icristi wrote:
함수 포인터를 전달받는 함수를 쓰레드로 만들고 싶어서(pthread_creadte)
함수포인터를 void * 으로 형 변환 했습니다.

다시 함수 포인터로 형변환 하는 방법이 있을까요?

bool CMainThread::Create( void* (*func)(void*) )
{
       pthread_create( &m_hThread, NULL, &CMainThread::Run, (void*)func );
.
.
.


void* CMainThread::Run( void* func )
{

     //func 를 어떻게 함수로 쓸까요?

.
.
.
}



요즘 이것 저것 참 물어보는 것만 많네요...
KLDP에 도움이 되고자 하지만 지금 제 수준에서는 그저 이렇게
궁금증을 해소를 위한 하소연 밖에 못하네요....ㅜ.ㅜ

저도 언젠가 내공이 많이 쌓이면 왕성한~ 답변활동(?)을 통해
도움 받은 것 환원해야겠죠~~~ ^^;;

pynoos의 이미지

http://bbs.kldp.org/viewtopic.php?t=28039

static 으로 하지 않으면 형비교에서 달라지기 때문에 넘길 수가 없습니다. 물론 강제로 casting하고, 파라메터로 넘기는 void *에 this 를 넘겨서 멤버를 호출하는 방법도 있습니다.

보기에 안좋지만 C를 하부로 사용하려면 어쩔 수 없습니다.

chunsj의 이미지

네임 멩글링 문제 이외에도 실제로 형이 다르지 않나요? C++ 써본지가 좀 되서
잊어버렸는데, 형이 실제로 달랐던 것 같은데... 아, 그래서 캐스팅으로 되는
것이 아니었던 것으로 기억됩니다만...

pynoos wrote:
http://bbs.kldp.org/viewtopic.php?t=28039

static 으로 하지 않으면 형비교에서 달라지기 때문에 넘길 수가 없습니다. 물론 강제로 casting하고, 파라메터로 넘기는 void *에 this 를 넘겨서 멤버를 호출하는 방법도 있습니다.

보기에 안좋지만 C를 하부로 사용하려면 어쩔 수 없습니다.

icristi의 이미지

Quote:
질문에 이미 답이 있습니다. void *(*func) (void *);
좀 멋있게 하려면,
typedef void * (*ThreadHandlerFunc) (void *);
이렇게 해서 type casting을 하면 되겠죠. 꼭 안해도 되고...
혹시나 해서 예제를 쓰면 Run에서 func이 넘어왔다면
ThreadHandlerFunc doThis = (ThreadHandlerFunc)func;
이렇게 하고 doThis((void *)&aa); 뭐 이런식으로 쓸 수 있겠죠. 그런데

그냥 궁금해서 그러는데요...
typedef를 쓰지 않고
ThreadHandlerFunc doThis = (ThreadHandlerFunc)func;
이 구문을 표현하는 방법은 무엇일까요?

Quote:

꼭 이렇게 하시는 이유가 있으신지?

꼭 이렇게 하는 이유는요.
다음과 같은 클래스를 설계하고자 해서 입니다.
기본적으로 쓰레드 클래스인데, 이것으로부터 객체를 만들 때
쓰레드로 실행될 임의의 함수를 함수 포인터로 전달하여 instantiation 하고자
하는 것입니다.

이런 구조가 혹 정도에 맞지 않거나 비상식적인 것은 아닌지요?

여러분들의 친절하신 답변해 항상 감사합니다.

pynoos의 이미지

chunsj wrote:
네임 멩글링 문제 이외에도 실제로 형이 다르지 않나요? C++ 써본지가 좀 되서
잊어버렸는데, 형이 실제로 달랐던 것 같은데... 아, 그래서 캐스팅으로 되는
것이 아니었던 것으로 기억됩니다만...

맞습니다... static 아닌 member function은 일반함수로 상호 casting되지 않으며, static 을 사용해서 한단계 건너 뛰는 방식으로 밖에 되지 않습니다.

일반함수의 void * 에 객체의 this 를 넘겨 나중에 다시 staic 함수내에서 ((AClass *)pv)-> 이런 형태로 복원하여 접근하는 방법밖에는 되지 않습니다.
그 방법이 c 함수의 callback에 넣어 사용하는 가장 일반적인 방법으로 알고 있습니다.

이렇게 쓰는 방법을 말하려고 했는데, 짧게 인용만하려 끝내려다가.. :roll:

음.. 그런데, 왜 static 아닌 멤버함수와 일반함수는 상호 casting이 안될까요...
좀더 찾아 봐야겠습니다.

akbar의 이미지

icristi wrote:

pthread_create 에 원래 static 함수 밖에 쓰지 못하나요?
멤버 함수 &Run 을 그냥 쓰니까 저런 에러메세지가 나오네요.
static으로 바꾸니까 되긴 해요...

static 혹은 전역 함수 밖에 쓸 수가 없습니다.
멤버 함수의 경우 this 포인터가 반드시 필요한데
위의 경우

&CMainThread::Run 이라고

멤버함수 포인터를 넘겨도
this 포인터를 같이 전달하는 것이 아니기 때문에
컴파일러가 오류를 내는 것이지요
만약 이런 문법이 허용된다면
CMainThread::Run() 함수가 멤버 변수에 접근하는 경우 어느 객체의 멤버에 접근하는 지를 알 수 없으므로 큰일 나게 됩니다.
정적 멤버 함수는 this 포인터를 필요로 하지 않으므로
일반 함수처럼 캐스팅이 자유롭습니다.

marten의 이미지

인텔머신에서 C 함수의 callback function으로 C++ 클래스의 멤버함수를 사용하는 방법이 있습니다. C++ calling convention의 동작방식을 직접 구현하여 함수를 리다이렉션해주는 방법입니다. 그 방법이 재미있어서, 참고삼아 관련 URL을 올려봅니다.

단, 인텔머신이 아닌 다른 머신에서 사용하려면 코드를 수정해야 합니다.

http://www.codeproject.com/cpp/thunk.asp?print=true

아참, 위에서 제공하는 코드는 WIN32 + Visual C++ 컴파일러에 의해 동작하는 코드입니다.
이걸 리눅스 + gcc 에서 동작하도록 만들 수도 있지 않을까요?

marten의 이미지

icristi wrote:
그냥 궁금해서 그러는데요...
typedef를 쓰지 않고
ThreadHandlerFunc doThis = (ThreadHandlerFunc)func;
이 구문을 표현하는 방법은 무엇일까요?

아래 방법처럼 하면 될듯 합니다.

ThreadFunc(void * func)
{
   void * (* real_func) (void *) = (void * (*)(void *))func; 
   real_func(...);
}
catzbi의 이미지

class test_vitrual_interface_set { 
public: 
	// global func set ; accesible [ from all ] 
private:
protected: 
	// sub func set ; with keyword friend ; 
	// virtual is collateral with friend ; ? 
}; 


class test : public { 
private : /* useless for friend specialization */  /*wrapping*/ 
	friend void* hello (void* ) { 
		// ..some 
	} 
public: 
	//somehwere () { 
	//			traverse ( from ' global func set ' ) ; with a thread ; 
	//
	//			automatic termination ; 
	//				] 
};

-,.-;; 클래스 내부에서 재정의된( 외부접근 불가한?friend??) 함수들의모임을 가지고서
, member function 으로 정의되지 않고서도 thread routine 으로 사용
되는 것을 보고 있음..

pynoos의 이미지

pynoos wrote:
chunsj wrote:
네임 멩글링 문제 이외에도 실제로 형이 다르지 않나요? C++ 써본지가 좀 되서
잊어버렸는데, 형이 실제로 달랐던 것 같은데... 아, 그래서 캐스팅으로 되는
것이 아니었던 것으로 기억됩니다만...

맞습니다... static 아닌 member function은 일반함수로 상호 casting되지 않으며, static 을 사용해서 한단계 건너 뛰는 방식으로 밖에 되지 않습니다.

일반함수의 void * 에 객체의 this 를 넘겨 나중에 다시 staic 함수내에서 ((AClass *)pv)-> 이런 형태로 복원하여 접근하는 방법밖에는 되지 않습니다.
그 방법이 c 함수의 callback에 넣어 사용하는 가장 일반적인 방법으로 알고 있습니다.

이렇게 쓰는 방법을 말하려고 했는데, 짧게 인용만하려 끝내려다가.. :roll:

음.. 그런데, 왜 static 아닌 멤버함수와 일반함수는 상호 casting이 안될까요...
좀더 찾아 봐야겠습니다.

저런... 오늘 아침 출근하다가.. 생각나서..

둘은 calling convention이 다른부류입니다.
하나는 일반 cdecl 이겠고, 하나는 this-call 이겠죠... calling convention이 다른 함수간의 casting은 일어나지 않습니다.

yielding의 이미지

아래의 클래스 X가 있을때
class X {
public:
    void m1(int a) {}
    static void m2(int a) {}
};

모든 non-member function은 컴파일러에 의해서 implicit하게 const X* this가 첫번째 인자로 들어갑니다..

이렇게
void X::(const X*this, int a) {

}

static function은 this가 자동으로 들어가지 않지요.

그래서 casting이 안될거에요. 그리고 pthread_create의 인자로도
signature가 다르므로 사용이 될 수 없죠.. (non-static member function..)

Life rushes on, we are distracted

댓글 달기

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