C++ face detection combined with c# WPF - c++

I downloaded and studied a code in C++, where Caffe and OpenCV are used for Face Recognition. At the moment, the code is written as a Console Application, that opens a window with the "Livestream" of the webcam and the face recognition.
Now i read that if I want to add the program to WPF, I need to make the C++ part a DLL, that gets implemented into C#. But my problem atm is this code:
int init(int argc, const char** argv)
{
char acUserName[100];
string UserName;
DWORD nUserName = sizeof(acUserName);
if (GetUserName(acUserName, &nUserName)) {
UserName = acUserName;
string errorPath = "C:/Users/" + UserName + "/Desktop/ErrorLog.txt";
const char *errorChars = errorPath.c_str();
...
}
I found this code for getting the current username in c++, the init method is actually the main, just with a new name. But when I type this code in my DLL-version, Visual Studio gives the Error
argument of type "char*" is incompatible with parameter of type "LPWSTR"
and the "acUserName" in
if (GetUserName(acUserName, &nUserName))
is marked. How can I fix this?
(I'm beginner in C++, if you guys need more code, tell me)

It sounds like charset error.try to change charset to multibyte in VisualStudio Project Setting.

There are wide-string and ASCII versions for API functions, which have 'W' or 'A' appended to the function name respectively. The GetUserName uses the wide-string variant by default.
If you don't care about Multibyte character strings, you can use GetUserNameA, with the parameters: &UserName[0] and the predefined length of the string.
However if you do, then just change the type of UserName to a wstring, and then pass the parameters to the function in the same way. Don't forget to include 'wstring.h' as well.

Related

how to convert char* to LPCTSTR in c++(MFC)

I have to make MFC application that accesses .txt files.
The following code is part of the template file given:
fopen(dlg.GetPathName());
However when I tried to run given template file, I got errors indicating that char* can not be converted to LPCTSTR.
I did some research online, and the program runs fine after correcting like this:
USES_CONVERSION;
const char* cstr;
cstr = T2A((LPCTSTR)dlg.GetPathName());
~
fp = fopen(cstr, "r");
I'm mentioning this because my compiler(VS 2017 community) may use unicode as default. And I think this is key to solving the aforementioned problem:
I have a problem printing result on the window edit control.
m_Result.SetWindowTextW((LPCTSTR)Result);
Result contains the message to be displayed in edit control and its type is char*. Whenever I run the program the result it is displayed either in blank box □ or Chinese. I tried converting Result using A2T and CA2T and but none of these worked.
The first error can be fixed by using Microsoft's _wfopen() function (or the TCHAR equivalent, _tfopen(), to match the TCHAR nature of GetPathName() instead of fopen(). That way, you don't need to convert the input string to char* at all:
fp = _wfopen(dlg.GetPathName(), L"r");
fp = _tfopen(dlg.GetPathName(), _T("r"));
In the second error, if Result is char* (or something that is implicitly convertible to char*) and LPCTSTR maps to const wchar_t* (because UNICODE is defined) then you can use CA2CT just fine:
m_Result.SetWindowTextW(CA2CT(Result));
However, since SetWindowTextW() expects only wchar_t* and never TCHAR*, use CA2CW instead:
m_Result.SetWindowTextW(CA2CW(Result));
Alternatively, if possible, you should change Result to use wchar_t instead of char in the first place, then you don't need a conversion anymore:
m_Result.SetWindowTextW(Result);

Understanding Multibyte/Unicode

I'm just getting back into Programming C++, MFC, Unicode. Lots have changed over the past 20 years.
Code on another project compiled just fine, but had errors when I paste it into my code. It took me 1-1/2 days of wasted time to solve the function call below:
enter code here
CString CFileOperation::ChangeFileName(CString sFileName)
{
char drive[MAX_PATH], dir[MAX_PATH], name[MAX_PATH], ext[MAX_PATH];
_splitpath_s(sFileName, drive, dir, name, ext); //error
------- other code
}
After reading help, I changed the CString sFileName to use a cast:
enter code here
_splitpath_s((LPTCSTR)sFileName, drive, dir, name, ext); //error
This created an error too. So then I used GetBuffer() which is really the same as above.
enter code here
char* s = sFileName.GetBuffer(300);
_splitpath_s(s, drive, dir, name, ext); //same error for the 3rd time
sFileName.ReleaseBuffer();
At this point I was pretty upset, but finally realized that I needed to change the CString to Ascii (I think because I'm set up as Unicode).
hence;
enter code here
CT2A strAscii(sFileName); //convert CString to ascii, for splitpath()
then use strAscii.m_pz in the function _splitpath_s()
This finally worked. So after all this, to make a story short, I need help focusing on:
1. Unicode vs Mulit-Byte (library calls)
2. Variables to uses
I'm willing to purchase another book, please recommend.
Also, is there a way to filter my help on VS2015 so that when I'm on a variable and press F1, it only gives me help for Unicode and ways to convert old code to unicode or convert Mylti-Byte to Unicode.
Hope this is not to confusing, but I have some catching up to do. Be patient if my verbiage is not perfect.
Thanks in advance.
The documentation of _splitpath lists a Unicode (wchar_t based) version _wsplitpath. That's the one you should be using. Don't convert to ASCII or Windows ANSI, that will in general lose information and not produce a valid path when you recombine the pieces.
Modern Windows programming is Unicode based.
A Visual Studio C++ project is Unicode-based by default, in particular it defines the macro symbol UNICODE, which affects the declarations from <windows.h>.
All supported versions of Windows use Unicode internally throughout, and your application should, too. Windows uses UTF-16 encoding.
To make your application Unicode-enabled you need to perform the following steps:
Set up your project's Character Set to "Use Unicode Character Set" (if it's currently set to "Use Multi-Byte Character Set"). This is not strictly required, but it deals with those cases, where you aren't using the Unicode version explicitly.
Use wchar_t (in place of char or TCHAR) for your strings.
Use wide character string literals (L"..." in place of "...").
Use CStringW (in place of CStringA or CString) in an MFC project.
Explicitly call the Unicode version of the CRT (e.g. wcslen in place of strlen or _tcslen).
Explicitly call the Unicode version of any Windows API call where it exists (e.g. CreateWindowExW in place of CreateWindowExA or CreateWindowEx).
Try using _tsplitpath_s and TCHAR.
So the final code looks something like:
CString CFileOperation::ChangeFileName(CString sFileName)
{
TCHAR drive[MAX_PATH], dir[MAX_PATH], name[MAX_PATH], ext[MAX_PATH];
_tsplitpath_s(sFileName, drive, dir, name, ext); //error
------- other code
}
This will enable C++ compiler to use the correct character width during build time depending on the project settings

Strange error initializing a QApplication before using std::stod

I'm receiving an unexpected behavior in my current project.
I use the DICOM library dcmtk to read information from some dicom files, and Qt to show the images.
During the information extraction, I have to convert fields of the format "<64bit float>\<64 bit float>" (Dicom Tag PixelSpacing). I split into 2 strings at "\" and convert the strings into a double. So far, everything works fine.
Well, almost: whenever I create a QApplication object before I convert the strings to doubles, it gives me integers instead of doubles.
The code looks like this:
// Faulty situation
Database db;
QApplication app(&argc, argv);
db.fill_from_source(source); // here i get ints instead of doubles
// Rearrange code and recompile:
Database db;
db.fill_from_source(source); // now it gets me doubles.
QApplication app(&argc, argv);
// The fill function looks like this (simplified)
void Database::fill_from_source(const Source& source){
string s = source.get_pixel_spacing_string();
vector<string> s2 = split(s, "\\");
// get the double, that should not be integers!
double a = stod(s2[0]);
double b = stod(s2[1]);
}
It confuses me even more, that it does work stepping through the code using QtCreator and GDB. However, when I run the executable, I get integers again.
So I tracked the issue down to the stod operation: I get the right strings out of the DICOM file, but after stod the numbers after the dot are just truncated. Same behavior with stdlib's strtod
Does the QApplication allocation does something with the std::stod function? Since everything happens while runtime, I do not understand how.
Replacing stod with QString::toDouble resolves the issue...
I'am using gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3), GNU ld (GNU Binutils for Ubuntu) 2.24.
Other code dependencies include Eigen3, Boost.Python. The code is built using a CMake project with QtCreator as IDE.
Has anyone an idea where this problem comes from? Is this a Qt bug?
Being one of the DCMTK developers, i.e. the DICOM toolkit you use, I wonder why you don't retrieve the floating point values directly from the DICOM data element "Pixel Spacing", I mean instead of retrieving the entire character string (including the backslash separator) first and then converting its components to individual floating point numbers. That way, there would be no problem at all with the current locale settings.
By the way, because of the locale settings issue we've introduced our own locale-independent OFStandard::atof() helper function :-)
std::stod behaviour depends on the currently installed C locale.
According to cppreference:
During program startup, the equivalent of std::setlocale(LC_ALL, "C"); is executed before any user code is run.
As pointed by #peppe in the comments, during QApplication's construction setlocale(LC_ALL, ""); is called on Unix, thus altering std::stod.
You can store the locale and set it back as follows:
std::string backup(
// pass a null pointer to query the current C locale without modifying it
std::setlocale(LC_ALL, nullptr)
);
QApplication app(&argc, argv);
// restore the locale
std::setlocale(LC_ALL, backup.c_str());
EDIT:
After rereading documentation for QCoreApplication, there is a paragraph about locale settings in detailed description:
On Unix/Linux Qt is configured to use the system locale settings by default. This can cause a conflict when using POSIX functions, for instance, when converting between data types such as floats and strings, since the notation may differ between locales. To get around this problem, call the POSIX function setlocale(LC_NUMERIC,"C") right after initializing QApplication, QGuiApplication or QCoreApplication to reset the locale that is used for number formatting to "C"-locale.
However #J.Riesmeier provided an interessant answer as one of the DCMTK developers.

Pass a wxString into a printf-style varargs function

I am learning to code in C using K&R II. I am tired of console apps and decided to get into a GUI environment. Decided to use Code Blocks and wxWidgets. All is installed properly and working. [Windows 7 x86, Code Blocks 13.12, wxWidgets 3.0.0]
I am following the Tutorials on WxWidgets. I am in Tutorial 9. I have it working, finally; there are mistakes in the instructions.
I modified my app to have 2 text boxes and a button vs one text box for the output and one combo box for the input.
Visual C++ environment is totally foreign to me.
For the Button click I would like instead of printing, "O brave new world!\n",
I would like to read what has been entered in textbox1 and print it into textbox2.
The instruction:
wxString Text = TextCtrl1->GetValue();
gets the string that has been entered in textbox1
I have a call to the function
void printg(char *fmt, ...);
I need to know how/what to change the ... argument to so it will passes the wxString Text in the form of an array, I think, to that printg function. I am sure the first thing I need to do is change the Text string to an array, or some way to pass the string itself.
UPDATE 01/08/13 3:35 PM
I cut the code from the Textbox Enter event and pasted it into the ButtonClick event and now I can get the text in Box one to box two.
Now, I need a way to pass the text from textbox 1 to one of my C files, do whatever the exercise is about and pass it back to the click event to be passed to the printg function.
NOTE: I see confusion about printg. I think it is a feature of wxWidgets that lets you print back to a GUI form rather than a console as printf does. It works.
I would put the code on here, but I do not know how. Tried before and get a message about it not being formatted properly.
Thanks for the replies.
Text.ToUTF8().data() gives you const char *
Also if you only want char* instead of const char * you can use const_cast<char *>(Text.ToUTF8().data())
The most convenient thing to do is to use wx equivalents of standard functions, i.e. wxPrintf() in this case, because they allow you to pass wxString (and also std::string, std::wstring, char* and wchar_t*) objects directly, without doing anything special. So you could simply write
wxString s = ...;
wxPrintf("My string is %s\n", s);
OTOH using either printf() or wxPrintf() is generally not very useful in GUI applications, you probably want wxLogMessage() or something similar.
If you have a string: char *str = {"this is my string"};
Then you can use printf() like this:
printf("%s\n", str);
Note, there is no printg() in the C language. And the prototype of the printf() statement allows for multiple arguments to be passed as long as there is a format specifier for each argument. For example, this shows 3 format specifiers, and three arguments:
printf("%s %d %f\n", str, 10, 13.5);
The "..." argument is called the ellipse argument. It's covered in the K&R book, section 7.3 (in my edition anyway). It can have 0 or more arguments in it, as described by the *fmt argument.
If you already have a string ready, just call it like this:
printf("%s",str);

How do I store value to string with RegOpenKeyEx?

I need to grab the path from the registry. The following code works except for the last part where I'm storing the path to the string. Running the debugger in Visual Studio 2008 the char array has the path, but every other character is a zero. This results in the string only being assigned the first letter. I've tried changing char res[1024] to char *res = new char[1024] and this just makes it store the first letter in the char array instead of the string. The rest of the program needs the path as a string datatype so it can't stay as a char array. What am I missing here?
unsigned long type=REG_SZ, size=1024;
string path;
char res[1024];
HKEY key;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes\\dsn\\shell\\open\\command"), NULL, KEY_READ, &key)==ERROR_SUCCESS){
RegQueryValueEx(key,
NULL,// YOUR value
NULL,
&type,
(LPBYTE)res,
&size);
RegCloseKey(key);
path = string(res);
}
You're getting back a Unicode string, but assigning it to a char-based string.
You could switch path's class to being a 'tstring' or 'wstring', or use RegQueryValueExA (A for ASCII).
You are compiling in Unicode. Go to Project Settings>Configuration Properties>General and change "Character Set" to "Not Set", and rebuild your project.
RegOpenKey is actually a macro defined in the WINAPI headers. If Unicode is enabled, it resolves to RegOpenKeyW, if not then it resolves to RegOpenKeyA. If you want to continue to compile under unicode, then you can just call RetgOpenKeyA directly instead of using the macro.
Otherwise, you'll need to deal with Unicode strings which, if needed, we can help you with also.
For C++, you may prefer to access the Registry using the ATL helper class CRegKey. The method for storing string values is QueryStringValue. There are other (somewhat) typesafe methods for retrieving and setting different registry value types.
It's not the best C++ interface (eg. no std::string support) but a little smoother than native Win32.