Author | Message | Time |
---|---|---|
gameschild | Have written a DLL for use with primarily C and C++ however someone wanted it to work with Visual Basic. I modified the code to change the Call Convention to __stdcall from __cdecl and it now works fine in Debug of Visual Basic. However when i run the compiled (release) version of the Visual Basic EXE there is an Access Violation when trying to read a string. The string is passed like this [code] public declare sub functionA lib "MyDLL.dll" (ByVal arg0 as String) [/code] and is called like this: [code] dim s as string call functionA(s) msgbox s [/code] the signiture in the dll is: [code] void __stdcall functionA(LPSTR msg) [/code] When i debug it from the DLL with the VB symbols, the DLL will take the pointer and copy data into the pointer correctly. However, when the function returns, Visual Basic has an Access Violation. If i look at the memory where the pointer is the data is set correctly. Oddly enough however, the address of data in Visual Basic has changed and is now equal to whatever String s was before it was sent to the function. Im not sure but i have the feeling that something is either playing with the stack or some part of my calling convention is incorrect. Any ideas? | March 11, 2005, 2:24 PM |
Adron | [code] dim s as string s = string(<put max length of string here>, 0) call functionA(s) s = left(s, instr(s, chr(0))-1) msgbox s [/code] | March 11, 2005, 4:13 PM |
gameschild | i did at one point try dim s as String * 80 but that didnt work, i will try this also though | March 11, 2005, 4:21 PM |
gameschild | Indeed. I have debugged the program from VC++ using the Visual Basics Symbols and it will crash on: [code] s = String(80, 0) [/code] with an Access Violation. | March 11, 2005, 4:27 PM |
Adron | [quote author=gameschild link=topic=10886.msg103342#msg103342 date=1110558476] Indeed. I have debugged the program from VC++ using the Visual Basics Symbols and it will crash on: [code] s = String(80, 0) [/code] with an Access Violation. [/quote] But... At that line it hasn't even used the DLL yet! | March 11, 2005, 5:15 PM |
R.a.B.B.i.T | Which means it's not a problem with the DLL :) | March 12, 2005, 2:51 PM |
gameschild | Probably. I changed the compiation options to generate P-Code rather than Native Code and it works in release mode now. Guessing the difference is that P-Code is slower. Any ideas why native compilation over P_code doesnt work? | March 14, 2005, 11:51 AM |
Kp | [quote author=gameschild link=topic=10886.msg103757#msg103757 date=1110801113]I changed the compiation options to generate P-Code rather than Native Code and it works in release mode now. Guessing the difference is that P-Code is slower. Any ideas why native compilation over P_code doesnt work?[/quote] Native code doesn't work because your code is still wrong. My guess is that P-Code is somehow trapping the error a little more gracefully, but you're still doing something you shouldn't be. Fix your code and native compilation should work again. | March 14, 2005, 3:40 PM |
Adron | Post all your code. Copy and paste it from the respective projects. | March 14, 2005, 11:02 PM |
gameschild | Due to the codes intended use etc i am unable to release it "as it is" in a public community such as this, however i will post extracts of the code renaming functions etc. This is the callback from Java -> C++ Wrapper [code] JNIEXPORT jobject JNICALL myWrapper::nativeMyCallBack (JNIEnv *, jobject, jobject){ myCallBack(); return( NULL ); } [/code] myCallBack is a pointer to a function in the C++ DLL as follows: [code] typedef void (CALLBACK* callBackVoidSig)(); FARPROC callBackEndTxn; void CALLBACK myCallBack() { theLog->LogEvent(EVENT_CALL, "myCallBack"); try { callBackVoidSig theCallBack = (callBackVoidSig)aCallBackPtr; theCallBack(); }catch(...) { theLog->LogEvent(EVENT_ERROR, "myCallBack"); } } [/code] Again this code calls to a callback pointer which has been set by the host application, in this case the VB Script and calls back with a void(void) signiture. In the Host application, Visual Basic, the following code is called back: [code] Public Declare Sub func1Lib "MyDLL.dll" (ByVal arg0 As String) [/code] [code] Dim data As String * 80 Public Sub myCallBack() frmMain.AddToList "myCallBack" Call func1(data) frmMain.AddToList "Callback was : " & data End Sub [/code] That method calls back into the DLL and calls func1 which is as follows: [code] void __stdcall func1(LPSTR msg) { theLog->LogEvent(EVENT_CALL, "func1"); if(initialised) { try { wrapper->Function1(msg); }catch(...) { theLog->LogEvent(EVENT_ERROR, "func1"); } }else{ theLog->LogEvent(EVENT_ERROR, "DLL Not Initialised"); } } [/code] As you can see that calls back to the wrapper, the wrapper code is as follows: [code] void myWrapper::Function1(LPSTR msg) { PreFunction(); jstring authMsg = (jstring)env->CallStaticObjectMethod(spcWrapperClass, funcion1); PostFunction(); copyMsgToBuff(msg, authMsg); return; } void myWrapper::PreFunction() { jvm->GetEnv((void**) &env, JNI_VERSION_1_2); jvm->AttachCurrentThread((void **)&env, NULL); env->PushLocalFrame(10); //added in 1.0.0.1 } void myWrapper::PostFunction() { env->PopLocalFrame(NULL); } void myWrapper::copyMsgToBuff(LPSTR buff, jstring msg) { if( msg == NULL ){ buff[0] = '\0'; return; } const char *str = env->GetStringUTFChars(msg, NULL); strncpy( buff, str, MAX_STR_LEN ); //MAX_STR_LEN = 80 - str in debug is len(20) } [/code] Now if you debug this you can see all this happening in the order here, until you get back to myCallBack in the Visual Basic code, as that function returns it seems to crash. | March 16, 2005, 9:56 AM |
Myndfyr | Is there a better way to do what you're trying to do? For example, since VB doesn't support multithreading natively, shouldn't you just let the call return rather than trying to perform a callback into VB? I mean, it seems kind of silly. Since you can't start a second path of execution, a callback is somewhat of a weird way of getting back into VB. Can you consider changing the way or the order in which your functions are called? | March 16, 2005, 10:13 PM |
Kp | Also, let me point out that the more languages you start trying to mix together the more likely you're going to do something wrong. Although I can't say for sure since you won't tell us what this is, it seems rather silly to try mixing Java, C++, and VB all in one process. If you really cannot get away from at least one of them, consider having them run as distinct processes and use IPC. | March 16, 2005, 10:35 PM |