since the reaper sdk is using an abstract c++ class interface, there is the potential problem with calling conversations of member functions. explained here:
http://www.reaper.fm/sdk/plugin/plugin.php
http://forum.cockos.com/showthread.php?t=34447
pre gcc(mingw) 4.6.0, thiscall differs between gcc and msvc.
http://en.wikipedia.org/wiki/X86_cal...tions#thiscall
but versions post 4.6.0 have added support for the same format as msvc (explicitly or by default in 4.7).
http://gcc.gnu.org/gcc-4.6/changes.html
http://lists-archives.org/mingw-user...ith-mingw.html
a test:
Code:
/*
c.h
this header describes the interface
*/
#ifndef _H_
#define _H_
/*
gcc 4.6.x supports explicit declaration of virtual members with __thiscall.
conversation defaults for such in 4.7.0. the new __thiscall conversation
is the same as in MSVC.
*/
#define THISCALL
#if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 6)
#undef THISCALL
#define THISCALL __thiscall
#elif defined __GNUC__
#error __thiscall not supported for GCC VER < 4.6.0
#endif
#define VTABLE_NULL = 0
#define EXPORT __declspec(dllexport)
// some func pointer
extern void (*somef_ptr)(void);
// abstract base class with a couple of pure virtual methods
class c
{
public:
virtual void THISCALL ptxt (const char *) VTABLE_NULL;
virtual void* THISCALL getsf (void) VTABLE_NULL;
virtual const char* THISCALL getstr (void) VTABLE_NULL;
virtual void tprintf (const char*, ...) VTABLE_NULL;
};
#endif // _H_
Code:
/*
dll.cpp
test library
g++ -W -Wall -shared dll.cpp -o dll.dll -s
cl /nologo /W3 /LD /MD dll.cpp /Fedll.dll
*/
#include "stdio.h"
#include "c.h"
// func pointer
void (*somef_ptr)();
// dll entry point receives pointer to class instance
extern "C"
{
void EXPORT dllcall(c *cptr)
{
cptr->ptxt("c::ptxt");
puts(cptr->getstr());
cptr->tprintf("tprintf:0");
cptr->tprintf("%s:%.0f", (const char*)"tprintf", 1.f);
*(void**)&somef_ptr = cptr->getsf();
somef_ptr();
}
}
Code:
/*
test.cpp
abstract interface test for mingw (dll) and msvc (exe)
g++ -W -Wall test.cpp -o test.exe -s
cl /nologo /W3 /MD test.cpp /Fetest.exe
out:
start
c::ptxt
c::getstr
tprintf:0
tprintf:1
somef
end
*/
#include "windows.h"
#include "stdio.h"
#include "stddef.h"
#include "stdarg.h"
#include "c.h"
typedef void (__stdcall *ptr_fn)(void*);
// address of to be returned via c::getf
void somef(void)
{
puts("somef");
}
// c_impl inherits from c
class c_impl : public c
{
public:
char str[1024];
c_impl(void) { strcat((char*)str, (const char*)"c::getstr\0"); }
~c_impl(void) { return; }
virtual void THISCALL ptxt (const char *);
virtual void* THISCALL getsf (void);
virtual const char* THISCALL getstr (void);
virtual void tprintf (const char*, ...);
};
// ptxt: prints some text from argument
void THISCALL c_impl::ptxt(const char *txt)
{
puts(txt);
}
// getsf: returns a pointer to 'somef'
void* THISCALL c_impl::getsf(void)
{
return (void*)(ptrdiff_t)&somef; // or (INT_PTR)&somef
}
// getstr: returns value of a data member
const char* THISCALL c_impl::getstr(void)
{
return str;
}
// getstr: variadic member that sets data member str and prints it
void c_impl::tprintf(const char* format, ...)
{
char buf[1024];
va_list args;
va_start(args, format);
vsprintf(buf, format, args);
va_end(args);
memset(str, 0, sizeof(str)*sizeof(char));
strcat((char*)str, (char*)buf);
puts(str);
}
// exe entry
int main(void)
{
HINSTANCE hinst;
FARPROC id;
ptr_fn fn;
c_impl cinst; // instantiate inherited
// load lib; get address of entry
puts("start");
if (!(hinst = LoadLibrary("dll.dll")))
goto err_lib;
if (!(id = GetProcAddress((HMODULE)hinst, "dllcall")))
goto err_id;
// set pointer; pass address of instance to entry
fn = (ptr_fn)id;
fn(&cinst);
goto free_lib;
// err
err_lib:
puts("err_lib");
goto end;
err_id:
puts("err_id");
free_lib:
FreeLibrary(hinst);
end:
puts("end");
return 0;
}
files:
http://dl.dropbox.com/u/1627980/c/test_dll.zip
mingw > 4.6.x:
ftp://ftp.equation.com/gcc/
if i'm not missing something, the same should work for reaper extensions.
with the cc not being compatible, introducing member function with a parameter and calling it, causes undefined behaviour between a mingw dll and msvc exe (e.g. not passing ecx as the first parameter).
--