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); }
>>"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?
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. ^^
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; }
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...)
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; }
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.
Aihe on jo aika vanha, joten et voi enää vastata siihen.