|
|
|
#1 |
|
Registered User
Join Date: Dec 2002
Location: Malaysia
Posts: 12
|
Plugin VC++ problem
I'm trying the V3 Plugin to read information from smart card reader. However the value passed to SS did not come out correct.
extern "C" MYKAD_API int myKadOpen(void){ int nResult = CardOpen(); //open reader} When the return value is int, the value passed to SS come out OK. extern "C" MYKAD_API LPCTSTR myKadRead(void){ int nResult = SelJPNApp(); //select JPN application in card} When passing "Hello World" no problem. When using (char*) or cast, message box displays actual value but the value passed to SS comes out as & Any idea how to solve this? |
|
|
|
|
|
#2 |
|
Tim
Join Date: May 2001
Location: Ottawa
Posts: 11,873
|
This isn't really a V3 plugin problem, it's a pointer problem.
You can't return a pointer to name, it exists on the stack, which is cleaned up as soon as you leave the myKadOpen function (so the pointer is to random garbage). You can verify this for your self with a simple test. Code:
LPTSTR test(void)
{
BYTE name[150] = "whatever\0";
LPTSTR result = (LPTSTR)name;
MessageBox(NULL, result, "in test", MB_OK); // this works
return result;
}
void main(void)
{
LPTSTR s = test();
MessageBox(0, s, "in main", 0); // this fails
free(s);
}
Code:
LPTSTR test(void)
{
BYTE name[150] = "whatever\0";
LPTSTR result = (LPTSTR)strdup((LPTSTR)name);
MessageBox(NULL, result, "in test", MB_OK); // this still works
return result;
}
void main(void)
{
LPTSTR s = test();
MessageBox(0, s, "in main", 0); // now this will work too
free(s);
}
|
|
|
|
|
|
#3 |
|
Registered User
Join Date: Dec 2002
Location: Malaysia
Posts: 12
|
Never done anything in C++ before but the V3 Plugin sample and your help makes it very easy.
Thank you again |
|
|
|
|
|
#4 |
|
Tim
Join Date: May 2001
Location: Ottawa
Posts: 11,873
|
One last thing, I forgot to free the pointer that was returned from the test function. That would have leaked memory on every call to test. Not good. I fixed the examples I posted earlier.
Note: Freeing the pointer in the first example (where the pointer is just garbage) is just as likely to crash your application as fail silently, depending on where it's pointing. Pointers in C/C++ aren't hard, the rules are simple, when you break them the compiler makes you pay ![]() Here are a couple of places you can start reading about pointers, but if you're going to be writing plugins I'd suggest picking up a good beginners book on C/C++. A tutorial on pointers and arrays in C A Beginner's Guide to Pointers |
|
|
|
|
|
#5 |
|
Registered User
Join Date: Dec 2002
Location: Malaysia
Posts: 12
|
Generic CallDll
That helps a lot and I managed to get the interface to smartcard reader to work.
To make it easier for us to connect to external dll, would it be possible to have a generic CallDll plugin that accepts 3 parameters, ie the dll name, input and result. The CallDll pass the parameters to myDll which can call the external dll, pass the input parameters and send back the result to CallDll. In this way, we can add any call to dll directly without having to modify and recompile the dll. I hope nc can help. Thank you. |
|
|
|
|
|
#6 |
|
Tim
Join Date: May 2001
Location: Ottawa
Posts: 11,873
|
To make a generic DLL calling plugin is a little tricky because you have to manage the call stack yourself instead of just calling a function. If all the functions in the DLL you want to call have the same signature i.e. take the same number and type of parameters and return the same type of value, then the job gets a LOT easier. It's still manageable as long as you know the signatures of the functions you want to call ahead of time.
You need at least 4 parameters for a generic function caller (i) the name of the DLL to use with LoadLibrary (ii) the name of the function to pass to GetProcAddress (iii) the input parameter(s) and (iv) the return variable. This is how the CallDll example plugin works it just has one function for each function you want to call. Since you can have optional input parameters you could actually do this all with one function and just use the function name to determine how to construct the call. |
|
|
|