From: marcus h <da...@gm...> - 2014-08-25 08:21:23
|
When generating R wrapper code from Swig, it doesn't handle pointers to pointers correct (or if I don't use Swig/R correct). It passes a pointer to a pointer even if it shouldn't (in the second function call, fnRDllTestCopy) This must be a bug when generating R code (or I use it incorrectly). (Full project to reproduce the problem https://umetrics.sharefile.com/d/s4aa392c862a49adb) This how it's created and the result Swig command to create the wrapper: swig.exe -r -c++ -o rfile.cpp RDllTest.i The exported code looks like typedef struct tagTestHandle { void* pReserved; } *TestHandle;RDLLTEST_API int RCDECL fnRDllTestPointer(TestHandle* pHandle); RDLLTEST_API int RCDECL fnRDllTestCopy(TestHandle pHandle); and from R I call dyn.load ("C:\Projects\RDllTest\Debug\RTest.dll") source("C:\Projects\RDllTest\RTest.R") handle <- tagTestHandle() fnRDllTestPointer(handle) fnRDllTestCopy(handle) // Returns -1 which indicates an error The C code looks like class TestClass { public: TestClass() : miTest(1234) {} int miTest; }; // This is an example of an exported function. RDLLTEST_API int fnRDllTestPointer(TestHandle* pHandle) { *pHandle = reinterpret_cast(new TestClass()); return 42; } RDLLTEST_API int fnRDllTestCopy(TestHandle pHandle) { TestClass* pClass = reinterpret_cast(pHandle); if (pClass->miTest != 1234) // Should be 1234 or there is an error return -1; return 42; } Generated R code fnRDllTestPointer = function(pHandle, .copy = FALSE) { if (inherits(pHandle, "ExternalReference")) pHandle = slot(pHandle,"ref") ;.Call('R_swig_fnRDllTestPointer', pHandle, as.logical(.copy), PACKAGE='RTest'); } attr(fnRDllTestPointer, 'returnType') = 'integer' attr(fnRDllTestPointer, "inputTypes") = c('_p_p_tagTestHandle') class(fnRDllTestPointer) = c("SWIGFunction", class('fnRDllTestPointer')) Start of fnRDllTestCopy fnRDllTestCopy = function(pHandle, .copy = FALSE) { if (inherits(pHandle, "ExternalReference")) pHandle = slot(pHandle,"ref") ;.Call('R_swig_fnRDllTestCopy', pHandle, as.logical(.copy), PACKAGE='RTest'); } attr(fnRDllTestCopy, 'returnType') = 'integer' attr(fnRDllTestCopy, "inputTypes") = c('_p_tagTestHandle') class(fnRDllTestCopy) = c("SWIGFunction", class('fnRDllTestCopy')) Generated C++ code SWIGEXPORT SEXP R_swig_fnRDllTestPointer ( SEXP pHandle, SEXP s_swig_copy) { int result; TestHandle *arg1 = (TestHandle *) 0 ; void *argp1 = 0 ; int res1 = 0 ; unsigned int r_nprotect = 0; SEXP r_ans = R_NilValue ; VMAXTYPE r_vmax = vmaxget() ; res1 = SWIG_R_ConvertPtr(pHandle, &argp1, SWIGTYPE_p_p_tagTestHandle, 0 | 0 ); if (!SWIG_IsOK(res1)) { SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "fnRDllTestPointer" "', argument " "1"" of type '" "TestHandle *""'"); }arg1 = reinterpret_cast< TestHandle * >(argp1);{try {result = (int)fnRDllTestPointer(arg1);} catch(std::string& stringReason) {const char* sData = (char*)stringReason.c_str(); SWIG_exception(SWIG_RuntimeError, sData); } catch(...) { SWIG_exception(SWIG_RuntimeError, "Unknown exception"); } } r_ans = Rf_ScalarInteger(result); vmaxset(r_vmax); if(r_nprotect) Rf_unprotect(r_nprotect); return r_ans; } SWIGEXPORT SEXP R_swig_fnRDllTestCopy ( SEXP pHandle, SEXP s_swig_copy) { int result; TestHandle arg1 = (TestHandle) 0 ; void *argp1 = 0 ; int res1 = 0 ; unsigned int r_nprotect = 0; SEXP r_ans = R_NilValue ; VMAXTYPE r_vmax = vmaxget() ; res1 = SWIG_R_ConvertPtr(pHandle, &argp1, SWIGTYPE_p_tagTestHandle, 0 | 0 ); if (!SWIG_IsOK(res1)) { SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "fnRDllTestCopy" "', argument " "1"" of type '" "TestHandle""'"); } arg1 = reinterpret_cast< TestHandle >(argp1); { try { result = (int)fnRDllTestCopy(arg1); } catch(std::string& stringReason) { const char* sData = (char*)stringReason.c_str(); SWIG_exception(SWIG_RuntimeError, sData); } catch(...) { SWIG_exception(SWIG_RuntimeError, "Unknown exception"); } } r_ans = Rf_ScalarInteger(result); vmaxset(r_vmax); if(r_nprotect) Rf_unprotect(r_nprotect); return r_ans; } |