• Welcome to Valhalla Legends Archive.
 

VB -> (C++)DLL -> VB (bang)

Started by gameschild, March 11, 2005, 08:24 AM

Previous topic - Next topic

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

public declare sub functionA lib "MyDLL.dll" (ByVal arg0 as String)


and is called like this:

dim s as string
call functionA(s)
msgbox s


the signiture in the dll is:

void __stdcall functionA(LPSTR msg)


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?

Adron


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

gameschild

i did at one point try
dim s as String * 80 but that didnt work, i will try this also though

gameschild

Indeed. I have debugged the program from VC++ using the Visual Basics Symbols and it will crash on:

s = String(80, 0)


with an Access Violation.

Adron

Quote from: gameschild on March 11, 2005, 10:27 AM
Indeed. I have debugged the program from VC++ using the Visual Basics Symbols and it will crash on:

s = String(80, 0)


with an Access Violation.

But... At that line it hasn't even used the DLL yet!

R.a.B.B.i.T

Which means it's not a problem with the DLL :)

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?

Kp

Quote from: gameschild on March 14, 2005, 05:51 AMI 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?

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.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Adron

Post all your code. Copy and paste it from the respective projects.

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

JNIEXPORT jobject JNICALL myWrapper::nativeMyCallBack (JNIEnv *, jobject, jobject){
myCallBack();
return( NULL );
}


myCallBack is a pointer to a function in the C++ DLL as follows:

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");
}
}

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:

Public Declare Sub func1Lib "MyDLL.dll" (ByVal arg0 As String)



Dim data As String * 80

Public Sub myCallBack()
    frmMain.AddToList "myCallBack"
    Call func1(data)
    frmMain.AddToList "Callback was : " & data
End Sub


That method calls back into the DLL and calls func1 which is as follows:

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");
}
}


As you can see that calls back to the wrapper, the wrapper code is as follows:

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)
}


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.

MyndFyre

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?
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

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.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!