Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   [C/C++] cannot convert `const wchar_t*' to `const char*' (https://www.delphipraxis.net/78136-%5Bc-c-%5D-cannot-convert-%60const-wchar_t%2A-%60const-char%2A.html)

Luckie 29. Sep 2006 16:15


[C/C++] cannot convert `const wchar_t*' to `const char*'
 
Irgendwie mache ich einen Fehler, sehe ihn aber nicht mehr (es ist schon spät).

Code
Code:
   HINSTANCE hLib = LoadLibrary(DLLPATH);
UNICODE und _UNICODE ist definiert.

Im Code gibt er mir dann diesen Fehler aus:
Zitat:

error: cannot convert `TCHAR*' to `const WCHAR*' for argument `1' to `HINSTANCE__* LoadLibraryW(const WCHAR*)'
Was mache ich da falsch? :gruebel:

ste_ett 29. Sep 2006 16:20

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Die Funktion erwartet einen Pointer auf ein WCHAR, du übergibst aber einen Pointer auf ein TCHAR.
Versuche es mit einem einfachen Cast auf WCHAR*. :)

Luckie 29. Sep 2006 16:36

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Aber das würde doch die Verwendung von dem Datentyp TCHAR ad absurdum führen. Wenn cih dann ohne Unicode kompiliere, würde der Datentyp ja wieder nicht stimmen.

Btw bekomme ich jetzt noch komische Linkerfehler, die vorher nicht da waren. :gruebel: Aber das gucke ich mir am Montag an.

Olli 29. Sep 2006 21:04

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Code:
TCHAR* lpszDllPath = _T("kernel32.dll");
HINSTANCE hLib = LoadLibrary(lpszDllPath);
sollte mit oder ohne UNICODE/_UNICODE funzen ...

Luckie 29. Sep 2006 23:52

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Montag. ;) Aber die anderen Fehler die ich meine sind, dass er jetzt auf einaml Funktionen nicht mehr findet, die ich in einer anderen cpp-Datei habe und die ich über die Header-datei bekannt gmacht habe. Da muss ich am Montag noch mal gucken, was das ist. Aber erst seit ich UNICODE definiert habe. Mit TCHAR hatte ich vorher schon gearbeitet und alles in _T() gesetzt. Als ich dann UNICODE definiert habe, mochte er das mit dem _T() aufeinmal nicht mehr bei _tprintf(). :gruebel:

Luckie 2. Okt 2006 09:27

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Aha ja, jetzt geht es. Keine Ahnung, was das war. Aber gibt es keine Wide-String Version von GetProcAddress?
Code:
GetProcAddress(hLib, DLL_JNI_CREATE_JVM);
Das nimmt er nämlich nicht. Ich muss den Pfad erst nach char* zurückcaste. Aber dann findet er den Prozedur-Einsprungspunkt nicht. :gruebel:

EWeiss 2. Okt 2006 09:38

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Zitat:

Zitat von Luckie
Aha ja, jetzt geht es. Keine Ahnung, was das war. Aber gibt es keine Wide-String Version von GetProcAddress?
Code:
GetProcAddress(hLib, DLL_JNI_CREATE_JVM);
Das nimmt er nämlich nicht. Ich muss den Pfad erst nach char* zurückcaste. Aber dann findet er den Prozedur-Einsprungspunkt nicht. :gruebel:

versuch es doch einfach mal mit Ansi und unicode

erst unicode
LoadLibraryW((WCHAR*)lpszDllPath)
hier kein ergebnis dann Ansi
LoadLibrary(lpszDllPath);

dann bist auf ner sicheren seite.

gruß

Luckie 2. Okt 2006 09:52

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Es geht nicht um LoadLibrary, es geht um GetProcAddress. Und da ich die Datentypen TCHAR und das Makro _T benutze ist es egal, ob ich mit Unicode oder Ansi kompiliere. Definiere ich Unicode nimmt er automatisch die WideString Version der Funktion, kompiliere ich mit Ansi nimmt er die Ansi-Version. Beispiel:
Code:
#ifdef UNICODE
    return SetCurrentDirectoryW(
#else
    return SetCurrentDirectoryA(
#endif
Das ist nicht das Problem. Nur definiere ich die Prozedur so:
Code:
TCHAR* const DLL_JNI_CREATE_JVM = _T("JNI_CreateJavaVM");
und rufe GetProcAddress so auf:
Code:
FARPROC proc = GetProcAddress(hLib, DLL_JNI_CREATE_JVM);
Bekomme ich als Fehlermeldung:
Zitat:

cannot convert `TCHAR* const' to `const CHAR*' for argument `2' to `int (* GetProcAddress(HINSTANCE__*, const CHAR*))()'
Was mich etwas misstrauisch macht, ist die Tatsache, dass im PSDK kein Hinweis zu Unicode steht:
Zitat:

Implemented as GetCurrentDirectoryW (Unicode) and GetCurrentDirectoryA (ANSI). Note that Unicode support on Windows Me/98/95 requires Microsoft Layer for Unicode.
wie es sonst üblich ist.

Aus den Header-Dateien werde ich auch nicht schlau:
Code:
WINBASEAPI
FARPROC
WINAPI
GetProcAddress (
    __in HMODULE hModule,
    __in LPCSTR lpProcName
    );
Und:
Code:
//
// for GetProcAddress
//
typedef UINT (WINAPI* PGET_SYSTEM_WOW64_DIRECTORY_A)(__out_ecount_part_opt(uSize, return + 1) LPSTR lpBuffer, __in UINT uSize);
typedef UINT (WINAPI* PGET_SYSTEM_WOW64_DIRECTORY_W)(__out_ecount_part_opt(uSize, return + 1) LPWSTR lpBuffer, __in UINT uSize);

//
// GetProcAddress only accepts GET_SYSTEM_WOW64_DIRECTORY_NAME_A_A,
// GET_SYSTEM_WOW64_DIRECTORY_NAME_W_A, GET_SYSTEM_WOW64_DIRECTORY_NAME_T_A.
// The others are if you want to use the strings in some other way.
//
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_A_A     "GetSystemWow64DirectoryA"
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_A_W    L"GetSystemWow64DirectoryA"
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_A_T TEXT("GetSystemWow64DirectoryA")
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_W_A     "GetSystemWow64DirectoryW"
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_W_W    L"GetSystemWow64DirectoryW"
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_W_T TEXT("GetSystemWow64DirectoryW")

#ifdef UNICODE
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_T_A GET_SYSTEM_WOW64_DIRECTORY_NAME_W_A
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_T_W GET_SYSTEM_WOW64_DIRECTORY_NAME_W_W
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_T_T GET_SYSTEM_WOW64_DIRECTORY_NAME_W_T
#else
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_T_A GET_SYSTEM_WOW64_DIRECTORY_NAME_A_A
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_T_W GET_SYSTEM_WOW64_DIRECTORY_NAME_A_W
#define GET_SYSTEM_WOW64_DIRECTORY_NAME_T_T GET_SYSTEM_WOW64_DIRECTORY_NAME_A_T
#endif
Zu finden in WinBase.h.

Phoenix 2. Okt 2006 10:31

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Das sind genauch die Ecken warum ich C/C++ nicht wirklich mag. Dieses ganze rumgepointere auf die verschiedensten Typen kann einen noch verrückt machen.

Aber hier mal etwas Code zu GetProcAddress, den ich mir irgendwann mal für ein FH-Projekt ausm Netz zusammengesucht hab als ich den Program Files - Folder gesucht hab:

Code:
#include <windows.h>
#include <tchar.h>
#include <shlobj.h>

#define NUM_ELEMENTS(x) (sizeof((x)) / sizeof((x)[0]))

LPCTSTR lpszShell32  = TEXT("shell32.dll");
LPCTSTR lpszSHFolder = TEXT("shfolder.dll");

#ifdef UNICODE
  LPCSTR lpszGFP = "SHGetFolderPathW";
#else
  LPCSTR lpszGFP = "SHGetFolderPathA";
#endif

typedef HRESULT (WINAPI * SHGETFOLDERPATH)(HWND, int, HANDLE, DWORD, LPTSTR);

UINT_PTR GetProgramFilesFolder(LPTSTR lpFolder, UINT cchMax)
{
  SHGETFOLDERPATH pfnGFP;
  HINSTANCE      hDll;
  UINT_PTR       cch = 0;
  TCHAR          szFolder[MAX_PATH * 2];

    if(NULL != (hDll = LoadLibrary(lpszShell32)))
    {
        if(NULL != (pfnGFP = (SHGETFOLDERPATH)GetProcAddress(hDll, lpszGFP)))
        {
            if(SUCCEEDED(pfnGFP(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, szFolder)))
            {
                _tcsncpy(lpFolder, szFolder, min(cchMax, NUM_ELEMENTS(szFolder)));
                lpFolder[cchMax - 1] = TEXT('\0');
                cch = _tcslen(lpFolder);
            }
        }
        FreeLibrary(hDll);
    }

    if(!cch)
    {
        if(NULL != (hDll = LoadLibrary(lpszSHFolder)))
        {
            if(NULL != (pfnGFP = (SHGETFOLDERPATH)GetProcAddress(hDll, lpszGFP)))
            {
                if(SUCCEEDED(pfnGFP(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, szFolder)))
                {
                    _tcsncpy(lpFolder, szFolder, min(cchMax, NUM_ELEMENTS(szFolder)));
                    lpFolder[cchMax - 1] = TEXT('\0');
                    cch = _tcslen(lpFolder);
                }
            }
            FreeLibrary(hDll);
        }
    }

  return(cch);
}
Wie Du siehst wird in GetProcAddress einfach nur ein LPCSTR reingeworfen, und der wird je nach Bedarf (Unicode / nicht unicode) gefüllt.

Luckie 2. Okt 2006 10:43

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Hm, wenn ich nach LPCSTR caste, findet er den Prozedureinsprungspunkt auch nicht.

xaromz 2. Okt 2006 10:52

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Hallo,

ich habe mich gerade schlau gemacht: Es gibt keine Unicode-Version von GetProcAddress. Die Antwort auf das Warum ist einfach: Ein Funktionsname muss immer aus ASCII-Zeichen bestehen, deshalb ist eine Unicode-Version sinnlos.

Dir wird also nichts anderes übrigbleiben, als Deinen Unicode-String in einen Ansistring umzuwandeln (und nicht einfach nur zu casten).

Gruß
xaromz

Phoenix 2. Okt 2006 10:56

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Jetzt wo Du es sagst macht das tatsächlich Sinn ;-)

Luckie 2. Okt 2006 11:10

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
OK. Dann definiere ich die Konstante eben als char*. Ok, das geht ja dann.

Aber das Unicode macht mich noch wahnsinnig:
Code:
    _tprintf(_T("JNI_CreateJavaVM\n"));
   int status = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
#endif
       if (status != JNI_OK) {
       switch (status) {
          case JNI_ERR:
            _tprintf(_T("Error: %d\nunknown error\n"), status);
            break;
         case JNI_EDETACHED:
            _tprintf(_T("Error: %d\nthread detached from the VM\n"), status);
            break;
         case JNI_EVERSION:
            _tprintf(_T("Error: %d\nJNI version error\n"), status);
            break;
         case JNI_ENOMEM:
            _tprintf(_T("Error %d:\nnot enough memory\n"), status);
            break;
         case JNI_EEXIST:
            _tprintf(_T("Error %d:\nVM already created\n"), status);
            break;
         case JNI_EINVAL:
            _tprintf(_T("Error %d\ninvalid arguments\n"), status);
            break;
       }    
       return -1;
    }
    else {
       _tprintf(_T("JVM created successfully\n\n"));
    }
Ausgabe:
Zitat:

JNI_CreateJavaVM
J V M c r e a t e d s u c c e s s f u l l y
Das ist die Zeile vor dem Switch-Block und dann die Zeile im else-Abschnitt.
In der Konsole von Eclipse habe ich da lauter Rechtecke zwischen den Buchstaben und in der Windows Konsole sind es Leerzeichen. Warum macht er das aufeinmal? Die beiden Zeilen unterscheiden sich doch im Prinzip nicht von einander? :wall:

Phoenix 2. Okt 2006 11:31

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Hrm? Wenn Du die JVM in der zwischenzeit nicht lädst passiert das nicht, oder?
Was stellt denn die JVM mit der Ausgabe an? Wird da irgendwas umgebogen?

Luckie 2. Okt 2006 11:37

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Mist, wenn ich den Aufruf auskommentiere geht es. :wall: Der Funktionsaufruf scheint also da irgendwas zu verbiegen. Nehme ich eine MessageBox geht es.

Phoenix 2. Okt 2006 11:42

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Da wird dann aber irgendwas ganz kräftig umgebogen so dass eine Funktion die vorher Unicode handeln konnte es danach nicht mehr kann.

Da würde ich mal bei Sun (oder woher kommt diese JVM?) in einem Forum anklopfen und da nachhaken. Das kann ja eigentlich wirklich ned sein.

Olli 2. Okt 2006 18:40

Re: [C/C++] cannot convert `const wchar_t*' to `const char*'
 
Es ist immer ANSI oder ein Wert bis $FFFF, korrekt. Aber wenn man schonmal in die IAT und die Exporte von PE-Dateien geschaut hat, weiß man, daß es keine Unicode-Namen bei Funktionsnamen gibt - obwohl sowas wie UTF-7 oder UTF-8 denkbar wäre ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:43 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz