Hi and I am making a dll but the dll won't accept pointers due to what it links to. So below is my code and does anybody know how to make a string array without pointers? Also I'm using Visual c++ 2008.

//#pragma warning(disable:4996) //disable "depreciated function" warnings
#include <windows.h> //required for dll
#include <sstream>
#define DLLEXPORT extern "C" __declspec ( dllexport )


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

 DLLEXPORT std::string *explode (std::string exploder, std::string original, int limit=0) {
	std::string tmp;
	tmp=original;
	int num, loc, x, limiter;
	limiter=0;
	num=1;
	while (tmp.find(exploder)!=std::string::npos) {
		if (limiter==limit && limit!=0) { break; }
		if (limit>0) { limiter++; }
		loc=tmp.find(exploder);
		tmp=tmp.substr(loc+exploder.length());
		num++;
		}
	std::string *result;
	x=(num+1);
	result = new std::string[x];
	/*std::string s;
	std::stringstream out;
	out << x;
	s = out.str();
	result[0]=s;*/
	result[0]="1";
	num=1;
	tmp=original;
	while (tmp.find(exploder)!=std::string::npos) {
		if (limiter==limit && limit!=0) { break; }
		if (limit>0) { limiter++; }
		loc=tmp.find(exploder);
		result[num]=tmp.substr(0,loc);
		tmp=tmp.substr(loc+exploder.length());
		num++;
		}
	result[num]=tmp;
	return result;
}

Thanks...

Recommended Answers

All 22 Replies

memory allocated with new or malloc() in a DLL can not be deallocated by the main program because the memory has to be deallocated in the DLL. The same with memory allocated in the main program has to be deallocated there, the dll can not do it. The reason is because they are from different memory pools.

So the thing you should do for that function is to return the std::string object, not a pointer to it (just remove the star) and delete line 38. DLLEXPORT std::string explode (std::string exploder, std::string original, int limit=0) { Here is another thread about that discussion

I just tried removing the star at the top of the function and removing line 38 but I get the following error.

1>------ Build started: Project: gm_php, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>c:\documents and settings\owner\my documents\visual studio 2008\projects\gm_php\gm_php\main.cpp(23) : warning C4190: 'explode' has C-linkage specified, but returns UDT 'std::basic_string<_Elem,_Traits,_Ax>' which is incompatible with C
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1>c:\documents and settings\owner\my documents\visual studio 2008\projects\gm_php\gm_php\main.cpp(56) : error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(std::basic_string<_Elem,_Traits,_Ax>::_Has_debug_it)' : cannot convert parameter 1 from 'std::string *' to 'std::basic_string<_Elem,_Traits,_Ax>::_Has_debug_it'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> Constructor for struct 'std::basic_string<_Elem,_Traits,_Ax>::_Has_debug_it' is declared 'explicit'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1>Build log was saved at "file://c:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\gm_php\gm_php\Debug\BuildLog.htm"
1>gm_php - 1 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Also I tried removing the star at the beginning and the star at "result" variable then removed line 38 and got the following error.

1>------ Build started: Project: gm_php, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>c:\documents and settings\owner\my documents\visual studio 2008\projects\gm_php\gm_php\main.cpp(23) : warning C4190: 'explode' has C-linkage specified, but returns UDT 'std::basic_string<_Elem,_Traits,_Ax>' which is incompatible with C
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1>c:\documents and settings\owner\my documents\visual studio 2008\projects\gm_php\gm_php\main.cpp(44) : error C2440: '=' : cannot convert from 'const char [2]' to 'char'
1> There is no context in which this conversion is possible
1>c:\documents and settings\owner\my documents\visual studio 2008\projects\gm_php\gm_php\main.cpp(51) : error C2440: '=' : cannot convert from 'std::basic_string<_Elem,_Traits,_Ax>' to 'char'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>c:\documents and settings\owner\my documents\visual studio 2008\projects\gm_php\gm_php\main.cpp(55) : error C2440: '=' : cannot convert from 'std::string' to 'char'
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>Build log was saved at "file://c:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\gm_php\gm_php\Debug\BuildLog.htm"
1>gm_php - 3 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

It is like if it doesn't like std::string. Any suggestions?

I didn't notice you had extern "C" in that. In that case you can not return a std::string object, nor can any of its parameters be std::string because that is c++, not C.

What I would do if add another parameter for a buffer that is allocated in main application program, much like many of the win32 api functions do. This means you will also have to do some re-coding of that function to remove references to std::string.

DLLEXPORT BOOL explode (char* result, size_t resultsize, const char* exploder, const char* original, int limit=0) {

Then is it possible to convert that C to C++ because that is just the standard code I was given on line 4?

change line 4 to this: #define DLLEXPORT __declspec ( dllexport ) Now you will have a normal c++ function, which of course can not be called by any C program. But you will still want to change the return value so that it returns std::string instead of std::string *.

commented: Great help and advice +4

I just tried the below code but got the below error.

//#pragma warning(disable:4996) //disable "depreciated function" warnings
#include <windows.h> //required for dll
#include <sstream>
#define DLLEXPORT __declspec ( dllexport )


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

 DLLEXPORT std::string explode (std::string exploder, std::string original, int limit=0) {
	std::string tmp;
	tmp=original;
	int num, loc, x, limiter;
	limiter=0;
	num=1;
	while (tmp.find(exploder)!=std::string::npos) {
		if (limiter==limit && limit!=0) { break; }
		if (limit>0) { limiter++; }
		loc=tmp.find(exploder);
		tmp=tmp.substr(loc+exploder.length());
		num++;
		}
	std::string result;
	x=(num+1);
	//result = new std::string[x];
	/*std::string s;
	std::stringstream out;
	out << x;
	s = out.str();
	result[0]=s;*/
	result[0]="1";
	num=1;
	tmp=original;
	while (tmp.find(exploder)!=std::string::npos) {
		if (limiter==limit && limit!=0) { break; }
		if (limit>0) { limiter++; }
		loc=tmp.find(exploder);
		result[num]=tmp.substr(0,loc);
		tmp=tmp.substr(loc+exploder.length());
		num++;
		}
	result[num]=tmp;
	return result;
}

And the error was...

1>------ Build started: Project: gm_php, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>c:\documents and settings\owner\my documents\visual studio 2008\projects\gm_php\gm_php\main.cpp(44) : error C2440: '=' : cannot convert from 'const char [2]' to 'char'
1> There is no context in which this conversion is possible
1>c:\documents and settings\owner\my documents\visual studio 2008\projects\gm_php\gm_php\main.cpp(51) : error C2440: '=' : cannot convert from 'std::basic_string<_Elem,_Traits,_Ax>' to 'char'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>c:\documents and settings\owner\my documents\visual studio 2008\projects\gm_php\gm_php\main.cpp(55) : error C2440: '=' : cannot convert from 'std::string' to 'char'
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>Build log was saved at "file://c:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\gm_php\gm_php\Debug\BuildLog.htm"
1>gm_php - 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

It seems it is only recording a char in the array and not string. Any way around it? Thanks!

Anybody?

Didn't you bother to look at the problem line (line 44)?

>>result[0]="1";

result is a std::string, therefore you can not set the first character to a string. It should be result = "1";

Didn't you bother to look at the problem line (line 44)?

>>result[0]="1";

result is a std::string, therefore you can not set the first character to a string. It should be result = "1";

It is meant to be a string array and so in the array the first key contains the string "1". Then the computer generates the rest of the array results. So is there a different way I am meant to do it?

It is meant to be a string array

However you define it as

std::string result;

that is a single string.

I am afraid AD didn't realize what you are trying to achieve and pushed you in the wrong direction. Disregard his advice from post #2, yet honor one from the post #4.

The memory allocated with new or malloc() in a DLL can not be deallocated by the main program part is absolutely correct, but it doesn't prevent you from returning such memory to main program. Just provide a helper method in the DLL to dispose what you returned. Of course the cleanest way is to wrap everything in a class.

Post #4 isn't exactly what I planned to do. I am trying to recreate the php library meaning the inputs would need to stay the same as the documentation. But I'm just not sure on how to return a string array. Does anybody know the basics behind making a string array without a pointer?

>>Does anybody know the basics behind making a string array without a pointer?

Arrays in C and C++ are always pointers.

Well for some reason the code in post #1 returns only value[0]="0"; but doesn't return anything else. Even if I change the first array value it is still zero. Any reason for this unusual behavior?

What two parameter strings are you passing to that function so that I can test it ?

Why would you say that? Most experienced C/C++ forum posters are stuck spending way too damn much time trying to unexplain "arrays are pointers".

The only way to pass an array between functions is via pointers. I was just trying to be brief in the context of this thread.

The only way to pass an array between functions is via pointers. I was just trying to be brief in the context of this thread.

Close enough of a reason I guess, but do try to be clear and avoid the "arrays are pointers" kinda thing.

What two parameter strings are you passing to that function so that I can test it ?

If you like here is the official documentation. And the first param is what to search for. And in the second param it is the string to split and splits at every occurrence of param 1. But although I can use std::cout to output the correct results without the dll, as soon as I turn the project into a dll the function returns value[0]="0"; and nothing else. For example, the below exe code works.

#include <iostream>
#include <sstream>
std::string *explode (std::string exploder, std::string original, int limit=0) {
	std::string tmp;
	tmp=original;
	int num, loc, x, limiter;
	limiter=0;
	num=1;
	while (tmp.find(exploder)!=std::string::npos) {
		if (limiter==limit && limit!=0) { break; }
		if (limit>0) { limiter++; }
		loc=tmp.find(exploder);
		tmp=tmp.substr(loc+exploder.length());
		num++;
		}
	std::string *result;
	x=(num+1);
	result = new std::string[x];
	std::string s;
	std::stringstream out;
	out << x;
	s = out.str();
	result[0]=s;
	num=1;
	tmp=original;
	while (tmp.find(exploder)!=std::string::npos) {
		if (limiter==limit && limit!=0) { break; }
		if (limit>0) { limiter++; }
		loc=tmp.find(exploder);
		result[num]=tmp.substr(0,loc);
		tmp=tmp.substr(loc+exploder.length());
		num++;
		}
	result[num]=tmp;
	return result;
}
int main() {
	std::string *tmp;
	tmp=explode(".","a.b");
	std::cout << tmp[0] << "--" << tmp[1] << "-" << tmp[2] << std::endl;
	system("PAUSE");
	return 0;
}

But as soon as I turn it into a dll then tmp[1] and tmp[2] will nolonger exist and tmp[0] will equal "0" even with the same inputs but input dynamically from another program.

You must have something setup wrong because it worked ok in the dll for me. Here is the main() that I used.

[edit]Note: make sure you do not have more than one copy of that dll on your computer! [/edit]

#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <string>

#pragma comment(lib, "testdll.lib")
#define DLLEXPORT __declspec ( dllimport )
DLLEXPORT std::string *explode (std::string exploder, std::string original, int limit=0);
DLLEXPORT void FreeResult(std::string* result);


int main() {
	std::string *tmp;
	tmp=explode(".","a.b");
	std::cout << tmp[0] << "--" << tmp[1] << "-" << tmp[2] << std::endl;
    FreeResult(tmp);
	system("PAUSE");
	return 0;
}

And this is the dll

#include <iostream>
#include <sstream>

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

#define DLLEXPORT __declspec ( dllexport )
DLLEXPORT std::string *explode (std::string exploder, std::string original, int limit=0) 
{
	std::string tmp;
	tmp=original;
	int num, loc, x, limiter;
	limiter=0;
	num=1;
	while (tmp.find(exploder)!=std::string::npos) {
		if (limiter==limit && limit!=0) { break; }
		if (limit>0) { limiter++; }
		loc=tmp.find(exploder);
		tmp=tmp.substr(loc+exploder.length());
		num++;
		}
	std::string *result;
	x=(num+1);
	result = new std::string[x];
	std::string s;
	std::stringstream out;
	out << x;
	s = out.str();
	result[0]=s;
	num=1;
	tmp=original;
	while (tmp.find(exploder)!=std::string::npos) {
		if (limiter==limit && limit!=0) { break; }
		if (limit>0) { limiter++; }
		loc=tmp.find(exploder);
		result[num]=tmp.substr(0,loc);
		tmp=tmp.substr(loc+exploder.length());
		num++;
		}
	result[num]=tmp;
	return result;
}

DLLEXPORT void FreeResult(std::string* result)
{
    delete[] result;
}

Was that code to read the dll because if it was then I guess I will have to go to the gamemaker community to see why my dll won't work on gamemaker. It is like if the program reading the dll doesn't like arrays.

>>Was that code to read the dll
Not sure what you mean by that. C/C++ programs don't read DLLs but just simply call the functions.

Attached are the two projects I created, under a common folder named dvlp

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.