Originally Posted by
Bubba
You cannot return a std::string without problems as has been mentioned. You also do not want to return a pointer to memory that was allocated inside of a DLL and then de-allocate or call delete on that pointer from outside of the DLL. This will corrupt the heap of the module that is attempting to the clean up because it's CRT does not know about the allocation. Your best bet is to do something like this:
Code:
unsigned int GetStringLength();
void GetString(char *pBuffer,unsigned int length);
The client calls GetStringLength() and then allocates a char array of that size. GetString() is then called by the client and the array it allocated is passed in as a param. The length is passed in as a simple buffer overrun check. Even though the DLL knows the length of the string this type of function could be used to execute a buffer overrun exploit so you will want to pass in the length. Do a memcpy for this length from the DLLs string buffer to the buffer passed to the function. Check to ensure that the length passed in matches the length of the string and only copy at max the length of the string into the buffer. This does not ensure that the array passed in is actually the correct size and the code could still crash if it is not. This will work and it is clunky but it ensures that the client allocates the memory for the resulting string and thus can correctly clean it up and it does not expose the actual string in the DLL to external clients who could then misuse this and wreak havoc. Keep in mind if you wish to return a null terminated string you must allocate an array of sufficient size to accomodate for that.
Understand that the std::string approach will work as long as the client of the DLL and the DLL are guaranteed to use the same version of the STL. So if this is the case you may be wasting cycles solving a problem that may never happen in your program.
Thanks for your help but most of that is over my head, i did however find a function that converts a string to a char,
Code:
char *convertStringToChar(const string &str)
{
char *retPtr(new char[str.length() + 1]);
copy(str.begin(), str.end(), retPtr);
retPtr[str.length()] = '\0';
return retPtr;
}
and this all seems to work, also if i add a MessageBox in the code(for debugging purposes) it does show the right "line" from the text file when calling it from VB, however in the next line when the dll actually tries to return the (now char) data back to VB, well VB crashes giving me the error, "The instruction at "xxxxxx" referenced memory at "xxxxxxx". The memory could not be read. I know i am declaring the function correct in VB as there is only one way to do so. Here is what i have, any more ideas?
Code:
using namespace std;
BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved){
return TRUE;
}
char *convertStringToChar(const string &str)
{
char *retPtr(new char[str.length() + 1]);
copy(str.begin(), str.end(), retPtr);
retPtr[str.length()] = '\0';
return retPtr;
}
extern "C" __declspec( dllexport ) __stdcall const char* sSearch(char *);
extern "C" __declspec( dllexport ) __stdcall const char* sSearch(char* strString)
{
char* search = strString; // search pattern
int offset;
string line;
ifstream Myfile;
Myfile.open ("c:\\example.txt");
if(Myfile.is_open())
{
While (!Myfile.EOF())
{
getline(Myfile,line);
if ((offset = line.find(search, 0)) != string::npos) {
//cout << "found '" << line <<endl;
char *dPtr(convertStringToChar(line));
MessageBox(NULL, dPtr, NULL, NULL); // This (dPtr) give the correct result i have successfully converted a string to a char
return dPtr; // This crashes my VB app
}
}
Myfile.close();
}
return 0;
}