I have the following method :
VariantFromString(strXMLPath ,vXMLSource);
and the signature of the method is:
HRESULT VariantFromString(PCWSTR wszValue, VARIANT &Variant);
Now while I am passing a CString as below:
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
return errno;
}
CString strXMLPath = cCurrentPath;
strXMLPath += XMLFILE;
VariantFromString(strXMLPath ,vXMLSource);
I am getting the error: Can not Convert from CString to PCWSTR
You really should be using Unicode (wchar_t instead of char). That is how the OS operates internally, and would prevent having to constantly convert between char types like this.
But in this scenario, you could use CString::AllocSysString to convert it to a BSTR, which is compatible with PCWSTR. Just make sure it gets freed with SysFreeString.
[edit]
For example, you could change your function to:
VARIANT VariantFromString(const CString& str)
{
VARIANT ret;
ret.vt = VT_BSTR;
ret.bstrVal = str.AllocSysString();
return ret;
}
Related
I am trying to call a C# library from C++. Here's the function that makes the first call:
CapsReport::CapsReport(const CCOMString& reportFileName, CCDatabase* pDatabase)
: m_pDatabase(pDatabase), m_pReportServer(__uuidof(ReportServer))
{
::CoInitialize(NULL);
SetReportName(reportFileName);
// public void Load(string DSNname, string userName, string password, string reportFileName)
BSTR dsnBstr = pDatabase->DataSource().GetManagedBstr();
BSTR userBstr = pDatabase->UserName().GetManagedBstr();
BSTR passwordBstr = pDatabase->Password().GetManagedBstr();
BSTR reportNameBstr = ::SysAllocString(reportFileName);
m_pReportServer->Load(dsnBstr, userBstr, passwordBstr, reportNameBstr);
::SysFreeString(reportNameBstr);
}
By the time the Load() method is called, all three BSTRs returned by GetManagedBstr() contain the password. I'm trying to figure out why.
DataSource(), UserName() and Password() all return objects of type CCOMString:
CCOMString UserName() { return m_User; };
CCOMString Password() { return m_Pwd; };
CCOMString DataSource() { return m_DSN; };
I didn't want to have to call ::SysAllocString() and ::SysFreeString() every time I wanted to pass a CCOMString into a C# library, so I added a private BSTR member to the CCOMString class initialized to NULL. In the destructor, I check to see if that member is null. If it is not, I call ::SysFreeString() and set it to NULL.
The GetManagedBstr() method uses an existing member function of CCOMString named AllocSysString(). First, here's GetManagedBstr():
BSTR CCOMString::GetManagedBstr()
{
m_bstr = AllocSysString();
return m_bstr;
}
Now, here's AllocSysString():
BSTR CCOMString::AllocSysString() const
{
#ifndef _UNICODE
int nLen = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)m_pszString, GetLength(), NULL, NULL);
BSTR bstr = ::SysAllocString(NULL, nLen+1);
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)m_pszString, GetLength(), bstr, nLen);
#else
int nLen = _tcslen(m_pszString);
//BSTR bstr = ::SysAllocStringLen(NULL, nLen);
BSTR bstr = ::SysAllocString(m_pszString);
// _tcscpy_s(bstr, nLen, m_pszString);
#endif
return bstr;
}
m_pszString is merely the plain ordinary C++ string wrapped by CCOMString.
A BSTR object is a pointer. Somehow, all three BSTR objects are ending up pointing to the same memory location, even though they should have come from different CCOMString objects. How is this happening?
This point will not work. How to fix it. I understand that the CStrings leave the stack after the call to the function. are the any types of strings i C++ std:strings etc. Thats behave as C# strings. How I get it to work?
void Dialog1::GetOrderingKey(LPWSTR& lpOrderingKey)
{
CString OrderingKey;
m_Result.GetWindowText(OrderingKey);
lpOrderingKey = OrderingKey.GetBuffer(0);
}
LPWSTR lpOrderingKey;
GetOrderingKey(lpOrderingKey);
int returnValue = lpfnDllOrderingCodeDataW(lpSerialNumber, lpOrderingKey, data, _countof(data));
Just return a CString from GetOrderingKey():
CString Dialog1::GetOrderingKey()
{
CString OrderingKey;
m_Result.GetWindowText(OrderingKey);
return OrderingKey;
}
CString ordering_key = GetOrderingKey();
int returnValue = lpfnDllOrderingCodeDataW(lpSerialNumber, (LPCWSTR) ordering_key, data, _countof(data));
One straight forward and simplest way would be to declare it static.
void Dialog1::GetOrderingKey(LPWSTR& lpOrderingKey)
{
static CString OrderingKey;
I have a DLL written in C++ that wraps FindFirstFile/FindNextFile/FindClose to provide a file-search function:
std::vector<std::wstring> ELFindFilesInFolder(std::wstring folder, std::wstring fileMask = TEXT(""), bool fullPath = false);
This function returns a std::vector containing a list of filenames within the given folder matching the given filemask. So far so good; the function works as expected.
I need to write a C wrapper around this library, though, because I can't pass a vector across DLL boundaries. This is leading to no end of headaches.
I initially thought I would just set up a function that would receive a two-dimensional wchar_t array, modify it to contain the filename list, and return it:
bool ELFindFilesInFolder(const wchar_t* folderPath, const wchar_t* fileMask, const bool fullPath, wchar_t* filesBuffer[], size_t* filesBufferSize);
This proved to be a bad idea, however, as at least the second dimension's size has to be known at compile-time. I suppose I could just force the caller to make the second dimension MAX_PATH (so the function would receive a variable-length list of filename buffers, each MAX_PATH long), but this seems messy to me.
I considered a wrapper in the style of the Windows APIs:
bool ELFindNextFileInFolder(const wchar_t* folderPath, const wchar_t* fileMask, const bool fullPath, wchar_t* fileBuffer, size_t* fileBufferSize, HANDLE* searchToken);
This would perform the search, return the first filename found, and save the search handle provided by FindFirstFile. Future calls to ELFindNextFileInFolder would provide this search handle, making it easy to pick up where the last call left off: FindNextFile would just get the saved search handle. However, such handles are required to be closed via FindClose, and C doesn't seem to have the C++ concept of a smart pointer so I can't guarantee the searchToken will ever be closed. I can close some of the HANDLEs myself when FindNextFile indicates there are no more results, but if the caller abandons the search before that point there'll be a floating HANDLE left open. I'd very much like my library to be well-behaved and not leak HANDLEs everywhere, so this is out. I'd also prefer not to provide an ELCloseSearchHandle function, since I'm not sure I can trust callers to use it properly.
Is there a good, preferably single-function way to wrap these Windows APIs, or am I simply going to have to pick one from a list of imperfect solutions?
What about something like this?
In the DLL module:
#include <windows.h>
#include <vector>
#include <unordered_map>
unsigned int global_file_count; //just a counter..
std::unordered_map<unsigned int, std::vector<std::wstring>> global_file_holder; //holds vectors of strings for us.
/** Example file finder C++ code (not exported) **/
std::vector<std::wstring> Find_Files(std::wstring FileName)
{
std::vector<std::wstring> Result;
WIN32_FIND_DATAW hFound = {0};
HANDLE hFile = FindFirstFileW(FileName.c_str(), &hFound);
if (hFile != INVALID_HANDLE_VALUE)
{
do
{
Result.emplace_back(hFound.cFileName);
} while(FindNextFileW(hFile, &hFound));
}
FindClose(hFile);
return Result;
}
/** C Export **/
extern "C" __declspec(dllexport) unsigned int GetFindFiles(const wchar_t* FileName)
{
global_file_holder.insert(std::make_pair(++global_file_count, Find_Files(FileName)));
return global_file_count;
}
/** C Export **/
extern "C" __declspec(dllexport) int RemoveFindFiles(unsigned int handle)
{
auto it = global_file_holder.find(handle);
if (it != global_file_holder.end())
{
global_file_holder.erase(it);
return 1;
}
return 0;
}
/** C Export **/
extern "C" __declspec(dllexport) const wchar_t* File_Get(unsigned int handle, unsigned int index, unsigned int* len)
{
auto& ref = global_file_holder.find(handle)->second;
if (ref.size() > index)
{
*len = ref[index].size();
return ref[index].c_str();
}
*len = 0;
return nullptr;
}
/** C Export (really crappy lol.. maybe clear and reset is better) **/
extern "C" __declspec(dllexport) void File_ResetReferenceCount()
{
global_file_count = 0;
//global_file_holder.clear();
}
extern "C" __declspec(dllexport) bool __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, void* lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return true;
}
Then in the C code you can use it like:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main()
{
HMODULE module = LoadLibrary("CModule.dll");
if (module)
{
unsigned int (__cdecl *GetFindFiles)(const wchar_t* FileName) = (void*)GetProcAddress(module, "GetFindFiles");
int (__cdecl *RemoveFindFiles)(unsigned int handle) = (void*)GetProcAddress(module, "RemoveFindFiles");
const wchar_t* (__cdecl *File_Get)(unsigned int handle, unsigned int index, unsigned int* len) = (void*)GetProcAddress(module, "File_Get");
void (__cdecl *File_ResetReferenceCount)() = (void*)GetProcAddress(module, "File_ResetReferenceCount");
unsigned int index = 0, len = 0;
const wchar_t* file_name = NULL;
unsigned int handle = GetFindFiles(L"C:/Modules/*.dll"); //not an actual handle!
while((file_name = File_Get(handle, index++, &len)) != NULL)
{
if (len)
{
wprintf(L"%s\n", file_name);
}
}
RemoveFindFiles(handle); //Optional..
File_ResetReferenceCount(); //Optional..
/** The above two functions marked optional only need to be called
if you used FindFiles a LOT! Why? Because you'd be having a ton
of vectors not in use. Not calling it has no "leaks" or "bad side-effects".
Over time it may. (example is having 500+ (large) vectors of large strings) **/
FreeLibrary(module);
}
return 0;
}
It seems a bit dirty to be honest but I really don't know any "amazing" ways of doing it. This is just the way I do it.. Most of the work is done on the C++ side and you don't really have to worry about leaks.. Even exporting a function to clear the map would be nice too..
It would be better if the C exports were added to a template class and then export each of those.. That would make it re-useable for most C++ containers.. I think..
Change wchar_t* filesBuffer[] to wchar_t** *filesBuffer, then the caller can pass in a pointer to a wchar_t** variable to receive the array and does not need to know anything about any bounds at compile time. As for the array itself, the DLL can allocate a one-dimensional array of wchar_t* pointers that point to null-terminated strings. That way, your size_t* filesBufferSize parameter is still relevant - it receives the number of strings in the array.
bool ELFindFilesInFolder(const wchar_t* folderPath, const wchar_t* fileMask, const bool fullPath, wchar_t** *filesBuffer, size_t* filesBufferSize);
wchar_t **files;
size_t numFiles;
if (ELFindFilesInFolder(..., &files, &numFiles))
{
for(size_t i = 0; i < numFiles; ++i)
{
// use files[i] as needed ...
}
// pass files back to DLL to be freed ...
}
Another option is to do something similar to WM_DROPFILES does. Have ELFindFilesInFolder() return an opaque pointer to an internal list, and then expose a separate function that can retrieve a filename at a given index within that list.
bool ELFindFilesInFolder(const wchar_t* folderPath, const wchar_t* fileMask, const bool fullPath, void** filesBuffer, size_t* filesBufferSize);
bool ELGetFile(const wchar_t* fileName, size_t fileNameSize, void* filesBuffer, size_t fileIndex);
void *files;
size_t numFiles;
wchar_t fileName[MAX_PATH + 1];
if (ELFindFilesInFolder(..., &files, &numFiles))
{
for(size_t i = 0; i < numFiles; ++i)
{
ELGetFile(fileName, MAX_PATH, files, i);
// use fileName as needed ...
}
// pass files back to DLL to be freed ...
}
Any way you do it, the DLL has to manage the memory, so you have to pass some kind of state info to the caller and then have that passed back to the DLL for freeing. There is no many ways around that in C, unless the DLL keeps track of the state info internally (but then you have to worry about thread safety, reentrancy, etc) and frees it after the last file is retrieved. But that would require the caller to reach the last file, whereas the other approaches allow the caller to finish earlier if desired.
Hi i need in my project to concat the name of my dialogbox (type wchar_t) and the name of a configuration (type TCHAR).
How can i do this?
thanks.
This depends, a TCHAR is ether a char or wchar_t depending on whether you build your appication as Unicode or not. If you build your app as Unicode you can simply do:
wcscat_s(dest, extra);
If you do not build your app as Unicode, you need to either convert the string of TCHAR:s (which is then a string of char:s) into a string of wchar_t:s or your string of wchar_t:s into a string of char:s. To do that you should look into the MultiByteToWideChar or WideCharToMultiByte functions. Both of these can look a little bit scary taking a lot of parameters so I usually use some helpers (please note that proper error-handling has been removed for clarity, a proper solution would also call the functions mentioned above in a loop that resizes the buffer if the call fails with ERROR_INSUFFICIENT_BUFFER):
std::wstring multiByteToWideChar(const std::string &s)
{
std::vector<wchar_t> buf(s.length() * 2);
MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
s.c_str(),
s.length(),
&buf[0],
buf.size());
return std::wstring(&buf[0]);
}
std::string wideCharToMultiByte(const std::wstring &s)
{
std::vector<char> buf(s.length() * 2);
BOOL usedDefault = FALSE;
WideCharToMultiByte(CP_ACP,
WC_COMPOSITECHECK | WC_DEFAULTCHAR,
s.c_str(),
s.length(),
&buf[0],
buf.size(),
"?",
&usedDefault);
return std::string(&buf[0]);
}
In addition to those I set up a type-traits class so I can compile my projects as Unicode or not without caring:
template <class CharT>
struct string_converter_t;
template <>
struct string_converter_t<char>
{
static std::wstring toUnicode(const std::string &s)
{
return multiByteToWideChar(s);
}
static std::string toAscii(const std::string &s)
{
return s;
}
static std::string fromUnicode(const std::wstring &s)
{
return wideCharToMultiByte(s);
}
static std::string fromAscii(const std::string &s)
{
return s;
}
};
And an almost identical instance for the wchar_t (which I leave as an excerise). In your case you could then simply do:
std::wstring result = dialog_name + string_converter_t<TCHAR>::toUnicode(config_name);
You mean TCHAR*? Because it would be kinda weird to have a single character as a name. Anyways: Just cast the TCHAR's to wchar_t - TCHAR is either char or wchar_t, either way it's save to cast to wchar_t.
http://msdn.microsoft.com/en-us/library/cc842072.aspx
This question is similar to this: Cannot convert from 'const wchar_t *' to '_TCHAR *'
To manipulate different type of chars manually have a look at this: http://www.codeproject.com/KB/TipsnTricks/StringManipulations.aspx
Is there an direct way to manage C++/CLI Strings in a wrapper to char* parameter for native C++ method?!
example:
void Test::TestFunc(System::String ^%str)
{
// right conversion to char* and consider the reference
}
native C++ function:
void TestB::Func(char *str)
{
...
}
my tricky way:
void Test::TestFunc(System::String ^%szRecvBuffer)
{
pin_ptr<const wchar_t> szRecvBufferP = PtrToStringChars(szRecvBuffer);
// Convert to a char*
size_t origsize = wcslen(szRecvBufferP) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char nstring[newsize];
wcstombs_s(&convertedChars, nstring, origsize, szRecvBufferP, _TRUNCATE);
strcat_s(nstring, " (char *)");
char *szRecvBufferCh = nstring;
m_object->TestCommand(szRecvBufferCh); // parameter char*
System::String ^tmp = gcnew System::String(szRecvBufferCh);
szRecvBuffer = tmp;
}
greets leon22
You're doing a lot manually that the runtime will take care of for you.
void Test::TestFunc(String^% szRecvBuffer)
{
using System::Runtime::InteropServices::Marshal;
IntPtr memHandle = Marshal::StringToHGlobalAnsi(szRecvBuffer);
try
{
char* const str = static_cast<char*>(memHandle.ToPointer());
m_object->TestCommand(str);
szRecvBuffer = gcnew String(str);
}
finally
{
Marshal::FreeHGlobal(memHandle);
}
}
If you're using VC++ 2010, you can use std::unique_ptr<> with a custom deleter to avoid using try..finally, ultimately cutting the number of lines of code in half.
If the char* is an output parameter, then in C++/CLI you must pass System::StringBuilder^
If you search for "System::String" with Google, the second link is How to convert from System::String* to Char* in Visual C++ . This is obviously a FAQ!
(There appear to be about 5 different ways depending on the specifics of the conversion required, so I won't summarise them here: go read the article.)
You can't avoid having conversions in both directions, because System::String uses wchar_t, and a Unicode->Multibyte conversion is necessary to get char from that.
But marshal_as should make the conversion much easier.