Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: [C++] cannot convert from const char* to LPCTSTR

Tumettaja [24.02.2009 20:24:56]

#

Heipodei.

Käytössäni on Visual Studio 2008 Express Edition. Olen yrittänyt tehdä pienen laajennuksen (.dll) erääseen ohjelmaan, jossa tarvitsemaani funktiota ei ole valmiina. Kyseessä on siis winapi funktio URLDownloadToFile. Osaako joku neuvoa (täysin aloittelija kun olen) miksi seuraava koodi heittää otsikon mukaista erroria?

#include "stdafx.h"
#include "urlmon.h"
#define export extern "C" __declspec( dllexport )

export char* getsource () {
	LPCTSTR url = "http://www.google.fi";
	LPCTSTR file = "testi.txt";
	URLDownloadToFile(0,url,file,0,0);
}

Tommittaja [24.02.2009 20:33:13]

#

>>"cannot convert from 'const char to 'LPCTSTR": tuo const tarkoittaa vakiota, ja kuten varmaan tiedätkin, vakioita ei voi muuttaa :) (korjatkaa, jos olen väärässä)

Edit: hmm... jossain sanottiinkin näin: an LPCTSTR is another name for a const char *... :) luulin että se on joku... noh, en ollut ikinä kuullutkaan mistään LPCTSTR:stä.

Edit2: Asteriski?

Metabolix [24.02.2009 20:33:48]

#

Virhe tulee, koska LPCTSTR ja const char* (huomaa asteriski) ovat kaksi eri tyyppiä. Luultavasti kääntäjä siis käyttää funktioiden Unicode-versioita (hyvä), jolloin tekstinkin kuuluu olla Unicodea, mikä Windowsissa tarkoittaa suunnilleen UTF-16-enkoodausta. Koodissa tämä taas tarkoittaa, että tekstivakion eteen täytyy lisätä L, siis L"teksti". Parempi tapa on käyttää TEXT-makroa, joka lisää L:n tarvittaessa, jolloin koodi toimii sekä Unicodella että ilman käännösasetusten mukaan.

Tässä vielä tiivistelmä aiheeseen liittyvästä Windows-magiasta:

// Windowsin otsikot sisältävät:
#define  LPCTSTR  const TCHAR*
#ifdef UNICODE
  #define  TCHAR  wchar_t
  #define  TEXT(x)  L ## x
#else
  #define  TCHAR  char
  #define  TEXT(x)  x
#endif
// Esimerkkikoodi
LPCTSTR t = TEXT("moi");
// Unicode-käännös:
const wchar_t* t = L"moi";
// ANSI-käännös:
const char* t = "moi";

Tommittaja: Kannattaa ehkä jättää vastaamatta, jos ei ole aavistustakaan, mistä on kyse, etkä edes osaa kieltä. Sitä paitsi sinunkin pitäisi tuota koodia sen verran kyetä lukemaan, ettei tuossa mitään vakiota yritetä miksikään muuttaa. ^^

Tumettaja [24.02.2009 23:56:24]

#

Kiitoksia selkeästä vastauksesta Metabolix :]
Kysyn kuitenkin tähän samaan syssyyn vielä samantyylisen kysymyksen joka itseäni askarruttaa; miten onnistuu std::string muuttujatyypin muunnos char muotoon?

#include "stdafx.h"
#include "string.h"
#include "iostream"
#define export extern "C" __declspec( dllexport )

export char* funktio () {
    std::string merkkijono;
    //tässä lisätään edellisellä rivillä luotuun muuttujaan tekstiä
    //nyt pitäisi saada tungettua "merkkijonon" sisältö "restr" muuttujaan
    char restr[1000] = "(merkkijono muuttujan sisältö)";
    return restr;
}

Metabolix [25.02.2009 00:12:29]

#

Yllä merkkijono.c_str() palauttaisi osoittimen (const char *). Tätä ei kuitenkaan voi sijoittaa char-taulukkoon, vaan data täytyy kopioida for-silmukassa tai erillisellä funktiolla. Lisäksi funktiossasi on vakava virhe: paikallinen taulukko lopettaa olemassaolonsa funktion päättyessä, joten siihen osoittava osoitin ei varmastikaan toimi ohjelmassa oikein vaan voi aiheuttaa vaikka kaatumisen. Muisti täytyy sen sijaan varata dynaamisesti. Tällöin jonkun pitää tietenkin myös vapauttaa se, ettei tule muistivuotoa. C ja C++ käyttävät eri tapoja tähän, ja C:n ja C++:n tapoja ei pitäisi käyttää ristiin.

char *varaa(size_t koko) {
  return new char[koko];
  // return (char*) malloc(koko); // C
}
void vapauta(char *ptr) {
  delete [] ptr;
  // free(ptr); // C
}
char *varaa_kopio(std::string merkkijono) {
  char *muisti = varaa(merkkijono.size() + 1);
  strcpy(muisti, merkkijono.c_str()); // kopiointi
  return muisti;
  // Jonkun pitäisi myöhemmin kutsua vapauta(muisti).
}

Selvitä, kuinka muistin vapauttaminen tapahtuu käyttämässäsi ohjelmassa. Jos saat itse myös vapauttaa muistin, ongelmia ei pitäisi tulla.

(Olisit muuten voinut jatkaa siihen vanhaankin aiheeseen...)

Tumettaja [01.03.2009 16:47:02]

#

Palaan vielä aiheeseen, koska kohtasin funktiota tehdessä oudon ongelman, jota en ole onnistunut ratkaisemaan koska virhettä ei ole minulle ikinä ennen tullut. Edes hakemalla en löytänyt vastaavaan ognelmaan ratkaisua.
Käytössä on Visual C++ 2008 Express Edition.
Error-viesti kun yritän kääntää:

dllmain.obj : error LNK2019: unresolved external symbol _URLDownloadToFileW@20 referenced in function _downloadFile
1>C:\Users\MMMMMM\Documents\Visual Studio 2008\Projects\download\Debug\download.dll : fatal error LNK1120: 1 unresolved externals

Itse koodi:

#include "stdafx.h"
#include "urlmon.h"
#define export extern "C" __declspec( dllexport )

export double downloadFile () {
	LPCTSTR url = TEXT("http://www.google.fi");
	LPCTSTR file = TEXT("source.txt");
	URLDownloadToFile(0,url,file,0,0);
	return 1;
}

Metabolix [01.03.2009 16:53:45]

#

Pakko kysyä, miksi ihmeessä funktio palauttaa liukuluvun. Vaikea uskoa, että tämä olisi oikein tai järkevää.

Itse ongelmaan: Ohjelmaan täytyy linkittää urlmon-kirjasto. Tämän voit VS:ssa lisätä projektin asetuksiin, olisiko "Additional Libraries" tms.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta