Problem ze zwróceniem tablicy z DLLa

0

Witam serdecznie!!!
Na wstepie chce zaznaczyć że nie jest zbyt doświadczonym programistą, moje prace są raczej wymuszone przez konieczność realizacji projektów na uczelni, tak jest i tym razem.

Otóż moim zadaniem jest napisanie biblioteki DLL.
napisałem coś takiego:

CString zlozenie;
char infoczar[26];
extern "C" char __declspec(dllexport)

rotacja(int pol_1, int pol_2, int pol_3, int pol_4, int pol_5, int pol_6)
{

	CString dane_rot;
		
	CString dane0 = "1"; // znaczy że obrót

	CString param[6];
	param[0].Format("%d", pol_1);
	param[1].Format("%d", pol_2);
	param[2].Format("%d", pol_3);
	param[3].Format("%d", pol_4);
	param[4].Format("%d", pol_5);
	param[5].Format("%d", pol_6);

	dane_rot = dane0;
	if( formatowanie(param) !=0)
	{
		//wykrycie bledu z formatowania
		MessageBox(NULL, "Błąd przy wprowadzaniu danych", "Błąd", MB_ICONERROR | MB_OK);
	}

	dane_rot += zlozenie;
	
	char *wsk;
	wsk = infoczar;

	strcpy(wsk, dane_rot);
	return *wsk;
}

Mój zamysł był taki, aby funkcja rotacja wywołana z aplikacji pobierała inty z EditBoxów przerabiała je na CString, aby te dalej przekazać do funkcji formatowanie, która nie jest eksportowana z DLL do aplikacji. Efektem działania funkcji formatowanie jest tablica char (globalna tablica więc widziana w całej bibliotece). Tutaj kod funkcji formatowanie:

int formatowanie(CString iks[6])
{

	CString bufor ;

	for (int i = 0 ; i <6 ; i++)
	{
		if (iks[i].GetLength() == 0)
		{
			iks[i] = "+000";
		}

		if (iks[i].GetLength() == 1)
		{
			bufor = iks[i];
			iks[i] = "+00";
			iks[i] += bufor;
		}
		
		if (iks[i].GetLength() == 2)
		{
			if(iks[i].Find("-",0) == -1) //  jezeli nie ma minusa - daje +0 przed ciagiem
			{
				bufor = iks[i];
				iks[i] = "+0";
				iks[i] += bufor;
			}
			else
			{
				bufor = iks[i]; // a jezeli jest minus - daje -00 przed ciagiem
				iks[i] = "-00";
				iks[i] += bufor.Right(1);
			}
		}

		if(iks[i].GetLength() == 3) // jak sa trzy znaki:
		{
			if(iks[i].Find("-",0) == -1) // jezeli nie ma minusa - daje + przed ciagiem
			{
				bufor = iks[i];
				iks[i] = "+";
				iks[i] += bufor;
			}
			else
			{
				bufor = iks[i]; //a jezeli jest minus - daje -0 przed ciagiem
				iks[i] = "-0";
				iks[i] += bufor.Right(2);
			}
		}

		if(iks[i].GetLength()>4)// jezeli jest wiecej niz 4 znaki - wywala blad
		{
			return 1;
		}	

	}

	zlozenie = iks[0];
	zlozenie += iks[1];
	zlozenie += iks[2];
	zlozenie += iks[3];
	zlozenie += iks[4];
	zlozenie += iks[5];

	return 0;
}

Do tego miejsca wszystko działa jak trzeba, zmienna zlozenie przekazywana jest do funkcji rotacja i tam poprzez wskaźnik do zmiennej infoczar[26] jest kopiowana do tej zmiennej.
Problem pojawia się przy zwróceniu tej zmiennej przez funkcję rotacja do programu (zwrócenie zawartości tablicy z DLL do aplikacji), polega on na tym że rotacja zwraca do aplikacji tylko pierwszy element tej tablicy, a ja potrzebuje całą tablicę czyli np.: {1+000+000+000+000+000+000}

Proszę napiszcie co jest nie tak, tylko błagam nie piszcie mi że wszystko jest nie tak (bo i takie odp miałem na innych forach).
Nie proszę o napisanie tego za mnie, ale jeśli ktoś ma jakiś pomysł na zmianę kodu by działał tak jak tego chcę to będę wdzięczny :d

Z góry dziękuje!!!

0

nie wgłębiałem się w całość, więc nie powiem ci że "wszystko jest nie tak" ;) Powiem ci, co na pewno powoduje akurat twój problem:

żeby ci funkcja tablicę zwracała, przerób

extern "C" char __declspec(dllexport)

na

extern "C" char* __declspec(dllexport)

no i w związku z tym popraw returna, na return wsk;.
Cały czas oczywiście o funkcji rotacja mówimy. Tak tylko nawiasem i poza problemem dodam:

char *wsk;
wsk = infoczar;
strcpy(wsk, dane_rot);
return *wsk;

// nie prościej zapisać tak?

return strcpy(infoczar, (char*)dane_rot);
0

strcpy wypełnia ISTNIEJĄCY bufor. Nowy tworzy stddup. Czyli:

return strdupt((char*)dane_rot);

No i poza tym zawsze mnie to razi - zwracanie przez funkcję wskaźnika na pamięć, którą trzeba zwolnić własnoręcznie. Koszmar. Straszne. Zwłaszcza, że jest to interfejs DLL, a nie jakieś wewnętrzne mechanizmy.

Masz kilka normalnych, bespiecznych możliwości, ułożyłem w kolejności takiej, jakiej wg mnie byłoby najbardziej elegancko:

  • zwracaj CString lub std::string
  • przekazuj w parametrze wskaźnik na bufor, który funkcja ma wypełnić (tak jak to jest w funkcji strcpy).
  • auto_ptr (osobiście nie lubię)
  • ewentualnie chodź też nie polecam (musi być uzasadniony przypadek, tu raczej nie pasuje), zwracaj wskaźnik na wewnętrzny bufor w dll, wskaźnik ma ważność do następnego wywołania funkcji, funkcja zawsze korzysta z tego samego bufora lub go niszczy i tworzy nowy.
0

Gdy zrobie jak radziliście czyli:

extern "C" char* __declspec(dllexport)

kompilator wywala ostrzeżenie
warning C4518: '__declspec(dllexport ) ' : storage-class or type specifier(s) unexpected here; ignored

a aplikacja nie znajduje funkcji... :-(

0
extern "C" __declspec(dllexport) char* funkcja()
0

w VS musisz jeszcze mieć w opcjach, żeby tworzyło ci tablice importów w DLLce, bo jak nie to nawet takie zabiegi jak __declspec(dllexport) nic ci nie pomogą przy łączeniu dynamicznym.
Jak tworzysz projekt DLLki, musisz koniecznie zaznaczyć "export symbols" czy jakoś tak przy tworzeniu projektu, w opcjach nie pamiętam co się zmieniało...

0

Witam!!!

Serdeczne dzięki wszystkim!!!
Po przeczytaniu waszych rad i pokombinowaniu udało się:-)

Raz jeszcze dzięki za pomoc!!!

1 użytkowników online, w tym zalogowanych: 0, gości: 1