__stdcall 함수 포인터를 인자로 받는 함수의 오버로딩.

jaychoi의 이미지

__stdcall 함수 포인터를 입력으로 받는 함수와 __cdecl 함수 포인터를 입력으로 받는 템플릿 오버로딩 함수가 동시에 구체화 되면 symbol 이 이미 정의되어 있다는 에러 메세지가 발생합니다. 다음과 같은 예제에서 이런 문제가 발생합니다.

테스트 환경: DEVCPP 4.9.9.2 (g++ 3.4.2)

// #define __stdcall __attribute__((__stdcall__))
// #define __stdcall __attribute__((stdcall))
 
void foo(int) { }
void __stdcall bar(int) { }
 
template<class R, class P1>
void bind(R (* fn)(P1))
{
     std::cout << "__cdecl" << std::endl;
}
 
template<class R, class P1>
void bind(R (__stdcall * fn)(P1))
{
     std::cout << "__stdcall" << std::endl;     
}
 
int main(int argc, char *argv[])
{
    void (* fn_cdecl)(int);
    void (__stdcall * fn_stdcall)(int);
 
    fn_cdecl = &foo; // OK
    fn_stdcall = &bar; // OK
 
//    bind( foo ); // (1)
    bind( bar ); // (2)
 
    system("PAUSE");
    return EXIT_SUCCESS;
}

위에서 (1), (2) bind 중 어느 한 경우만 있는 경우에는 컴파일 문제가 없는데 (1), (2) 동시에 있는 경우에는 다음과 같은 메세지가 발생합니다.

Assembler messages: 
symbol `__Z4bindIviEvPFT_T0_E' is already defined 

함수 포인터에 호출 규약이 다른 경우에 오버로딩이 제대로 안되는 것으로 짐작됩니다. (물론 __stdcall 이 비 표준이긴 하지만...)
이 문제의 해결법이 없을까요?

-추가-
혹시나 해서 템플릿 bind 함수를 그냥 템플릿 제거하고 일반 함수로 하면 (1), (2) 관계없이 항상 같은 symbol이 이미 정의되어 있다는 에러를 발생시킵니다. (당연한 결과인가요? ^^)

익명사용자의 이미지

오버로딩은 함수 인자와 반환 값에 대한 정의이므로 호출 규약이 다른 같은 이름의 함수에는 사용할 수 없습니다. 다만 template에서는 호출 규약을 인식하는 것으로 보이므로 이 문제에 대해 간단한 꽁수를 생각해 볼 수 있습니다.

즉, template에서 다르게 인식한 두 함수의 인자를 다르게 주는 것입니다. (template에서 인식 한 함수가 실제로 오버로딩할 수 있는 함수로 보이게 하는 것이죠)

void bind(R (__stdcall * fn)(P1), int d = 0)
{
    std::cout << "__stdcall" << std::endl;
}

jaychoi의 이미지

꽁수가 아주 잘 동작하는군요. 정말로 감사드립니다.

댓글 달기

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 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.