2013-10-10 3 views
3

J'essaye d'obtenir a simple OpenCV sample fonctionnant en C++ sur Windows et mon C++ est plus que rouillé.Conversion de _TCHAR * en char *

The sample est assez simple:

#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream> 

using namespace cv; 
using namespace std; 

int main(int argc, char** argv) 
{ 
    if(argc != 2) 
    { 
     cout <<" Usage: display_image ImageToLoadAndDisplay" << endl; 
     return -1; 
    } 
    Mat image; 
    image = imread(argv[1], IMREAD_COLOR); // Read the file 
    if(! image.data)      // Check for invalid input 
    { 
     cout << "Could not open or find the image" << std::endl ; 
     return -1; 
    } 
    namedWindow("Display window", WINDOW_AUTOSIZE); // Create a window for display. 
    imshow("Display window", image);    // Show our image inside it. 
    waitKey(0); // Wait for a keystroke in the window 
    return 0; 
} 

Quand je fais une nouvelle application console C++ simple (avec ATL) dans Visual Studio 2012 je reçois un autre modèle pour main:

int _tmain(int argc, _TCHAR* argv[]) 

Alors avant J'envoie le nom de fichier à la fonction imread d'OpenCV dont j'ai besoin pour convertir le _TCHAR*arg[1] en char*. En utilisant un nom de fichier simple, « OpenCV-logo.jpg », de la mémoire dans la fenêtre de mémoire, je peux voir que le _TCHAR prennent deux octets chacun

o.p.e.n.c.v.-.l.o.g.o...j.p.g... 
6f 00 70 00 65 00 6e 00 63 00 76 00 2d 00 6c 00 6f 00 67 00 6f 00 2e 00 6a 00 70 00 67 00 00 00 

Suite à la recommandation de conversion en another answer Je suis en train d'utiliser ATL 7.0 String Conversion Classes and Macros en insérant le code suivant:

char* filename = CT2A(argv[1]); 

Mais la mémoire résultante est un gâchis, certainement pas 'OpenCV-logo.jpg' comme une chaîne ascii:

fe fe fe fe fe fe fe fe fe fe ... 
þþþþþþþþþþ ... 

Quelle technique, fonction ou macro de conversion dois-je utiliser?

(N.B. This peut-être une question connexe, mais je ne peux pas voir comment appliquer the answer ici.)

+0

Votre modèle de projet tente de créer un projet C++ pour le support Unicode. Je ne me souviens pas des options de projet/compilateur spécifiques, mais il devrait y avoir quelque chose à spécifier si vous utilisez unicode ou non. – OldProgrammer

+0

C'est dans la [page de propriétés générales du projet] (http://msdn.microsoft.com/en-us/library/vstudio/8x480de8.aspx) – user786653

+0

Avez-vous besoin d'un USES_CONVERSION; déclaration en haut de chaque fonction qui utilise les macros de conversion? –

Répondre

16

la solution la plus rapide est de simplement changer la signature au standard.Remplacer:

int _tmain(int argc, _TCHAR* argv[]) 

Avec

int main(int argc, char *argv[]) 

Cela ne signifie sur Windows que les arguments de ligne de commande sont converties à l'encodage des paramètres régionaux du système et que Windows ne supporte pas ici UTF-8 pas tout convertit correctement. Cependant, à moins que vous n'ayez besoin d'internationalisation, il ne vaut peut-être pas la peine de faire autre chose.

+0

J'ai essayé ceci - Je vais éditer la question pour expliquer ce que (je pense) s'est mal passé – dumbledad

+0

@dumbledad Okay. Commentez ici quand vous avez édité votre question pour recevoir une notification. – bames53

+2

@bames Cela ne fonctionne pas. La dernière fois que j'ai utilisé la signature 'int _tmain (int argc, char ** argv)' et le 'char *' fini comme '6f 00 70 00 65 00 6e 00 63 00 76 00 2d 00 6c 00 6f 00 67 00 6f 00 2e 00 6a 00 70 00 67 00 00 00' qui est le char 'c' suivi de' \ 0' et d'autres octets, ie la chaîne "c"! Echanger '_tmain' à' main' fait toute la différence, merci. – dumbledad

7

_TCHAR, à savoir TCHAR est un type qui dépend des paramètres de votre projet. Il peut s'agir de wchar_t (lorsque vous utilisez Unicode) ou char (lorsque vous utilisez Multi-byte). Vous trouverez dans Propriétés du projet - général, il y a un paramètre Jeu de caractères.

Probablement la chose la plus simple que vous pourriez faire est juste d'utiliser l'option multi-octets et traiter le _TCHAR* comme un simple char* et l'utiliser pour construire objet std::string dès que possible:

std::string filename(argv[1]); 

Mais dans le cas vous allez travailler avec des caractères spéciaux beaucoup, alors je trouve plus raisonnable d'utiliser Unicode et de maintenir les chaînes sous la forme d'objets std::wstring partout où c'est possible. Si tel est le cas, il suffit d'utiliser le constructeur de la place std::wstring:

std::wstring filename(argv[1]); 

Et au cas où vous finirez par travailler avec des chaînes larges, vous aurez parfois besoin d'une conversion entre les chaînes étendues et les chaînes multi-octets et ces aides pourraient vous aider:

// multi byte to wide char: 
std::wstring s2ws(const std::string& str) 
{ 
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0); 
    std::wstring wstrTo(size_needed, 0); 
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed); 
    return wstrTo; 
} 

// wide char to multi byte: 
std::string ws2s(const std::wstring& wstr) 
{ 
    int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), 0, 0, 0, 0); 
    std::string strTo(size_needed, 0); 
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), &strTo[0], size_needed, 0, 0); 
    return strTo; 
} 
+0

"Je vous recommande d'utiliser Unicode" Bien sûr, l'utilisation d'Unicode n'empêche pas d'utiliser 'char *'. Typiquement, je code les données Unicode en UTF-8 et je m'en tiens à 'char *'. – bames53

+0

@ bames53: Cela dépend du contexte du programme ainsi que des API qu'il va utiliser, mais j'avoue que le multi-octet semble être un meilleur choix ici. – LihO

+1

@ bames53: Vrai, mais malheureusement sur windows unicode implique plus ou moins utf-16 et 'wchar_t' car c'est ce que l'API win32 utilise. – user786653

-1

autre que la lecture du manuel cpp 2003 VS de 26 000 pages qui n'a pas beaucoup changé ... std :: string test (print); test = "";

int _tmain(int argc, _TCHAR* argv[]) 

int main(int argc, char *argv[]) 

travail même à moins que vous utilisiez une fonction securitys .... et ne pouvait pas être unicode dans la propriété jeu de caractères ... si vous deviez utiliser la fonction CreateFile dans le fichier des fonctions de gestion à moins que vous à plusieurs -Threaded en quelque sorte