Windows Semaphore and QSystemSemaphore - c++

I have a problem with semaphores in Windows between two application. An application waits for release signal(Qt) and the other application sends release signal(MSVC2008). But it dose not work.
I tested Qt-Qt and MSVC2008-MSVC2008 modes and they was succeed. But when I try Qt-MSVC2008 mode it fails.
// MSVC2008:
#include <windows.h>
#include <stdio.h>
int main()
{
const WCHAR semName[] = L"TestSem";
PHANDLE sem = (HANDLE *) CreateSemaphore (NULL, 0, 1, semName);
if (sem == NULL)
{
sem = (HANDLE *)OpenSemaphore (SEMAPHORE_ALL_ACCESS, 0, semName);
}
if (sem == NULL)
{
printf("OPEN/CREATE ERROR\n");
return 0;
}
BOOL r = ReleaseSemaphore(sem, 1 ,NULL);
if (r)
printf("OK\n");
else
printf("RELEASE ERROR\n");
CloseHandle (sem);
return 0;
}
and
// Qt 4.8.0 :
#include <QSystemSemaphore>
#include <QCoreApplication>
#include <iostream>
int main()
{
QSystemSemaphore *sem_read = new QSystemSemaphore("TestSem");
std::cout << "Wait for signal: " << std::endl;
while (1)
{
sem_read->acquire();
std::cout << "Hi" << std::endl;
}
return 0;
}
I expect when Qt-app is running, after executing MSVC2008-app, it prints one "Hi" in the screen. But it dose not. What is the problem?!
Note: I'm using Windows 7 and MinGW compiler for Qt

Looking at the Qt sources (4.7.3) I see at corelib/kernel/qsystemsemaphore_p.h:79 that the semaphore name generated by Qt is prefixed by qipc_systemsem_.
[UPDATE] The sha1 hash of "TestSem" is also appended, so the resulting Qt semaphore name is qipc_systemsem_TestSem3ec37c26f212774998f34a4e6722cac152ad17fa
Confirmed working.
To generate the semaphore name:
QString prefix = "qipc_systemsem_";
QString key = "TestSem";
QString result = prefix;
QString part1 = key;
part1.replace(QRegExp(QLatin1String("[^A-Za-z]")), QString());
result.append(part1);
QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex();
result.append(QLatin1String(hex));
qDebug() << result;

2 things I'd look into:
QSystemSemaphore requires an initial values and initiated with 0 if it is not given. Maybe start it with 1?
this is a system semaphore, could it be that your first test did not release it? try to change the name maybe.

Related

Disable CPU package idle states in Windows from C++ code

I am successfully disabling CPU core C-states using this code (I’m working on Win10 and use Qt):
#include <QCoreApplication>
#include <QDebug>
#include "Windows.h"
extern "C" {
#include "powrprof.h"
}
#pragma comment(lib, "powrprof.lib")
int main()
{
const DWORD DISABLED = 1;
const DWORD ENABLED = 0;
GUID *scheme;
int error;
error = PowerGetActiveScheme(NULL, &scheme);
qDebug() << "PowerGetActiveScheme error code = " << error;
error = PowerWriteACValueIndex(NULL, scheme, &GUID_PROCESSOR_SETTINGS_SUBGROUP, &GUID_PROCESSOR_IDLE_DISABLE, DISABLED);
qDebug() << "PowerWriteACValueIndex error code = " << error;
error = PowerWriteDCValueIndex(NULL, scheme, &GUID_PROCESSOR_SETTINGS_SUBGROUP, &GUID_PROCESSOR_IDLE_DISABLE, DISABLED);
qDebug() << "PowerWriteDCValueIndex error code = " << error;
error = PowerSetActiveScheme(NULL, scheme);
qDebug() << "PowerSetActiveScheme error code = " << error;
return 0;
}
The reason behind this is that I am running an USB camera and figured out that I’m losing data packets when the processor enters idle modes. The code above works fine and overcomes this issue successfully. But it’s actually a bit too much (disabling all C states appears to be unnecessary). I made some tests with the vendor software of the camera and found out that during acquisition not the core C-states stop, but the package C-states (if it is of any interest, I posted the analysis of this problem in the answer here https://superuser.com/questions/1648849/monitor-used-usb-bandwidth-in-win10).
So my question is: Can I adapt the above code to only disable package idle states? In case that’s not possible, can I selectively disable core C-states?
Update:
Based on the suggestion of #1201ProgramAlarm I tried to use SetThreadPriority() as in the minimal example below:
#include <QDebug>
#include <windows.h>
#include <conio.h>
#include "processthreadsapi.h"
int main()
{
bool ok = false;
ok = SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
qDebug() << "SetPriorityClass ok = " << ok;
ok = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
qDebug() << "SetThreadPriority ok = " << ok;
for (int i=1;i<100;i++) {
qDebug() << "Here I am in some dummy loop...";
if (_kbhit()) {
break;
}
Sleep(1000);
}
return 0;
}
Unfortunately, this doesn't help and when monitoring the cpu package idle states (using HWiNFO64) I see no effect (package goes still idle as before).
The system is shutting down the USB device to save power.
This link provides the solution USB system power issue.
Open the Device manager as administrator.
Find the camera.
On the "Power Management" tab, deselect "Allow the computer to turn off this device to save power".
This can be done programmatically if the device ID is known.

Why is if (fork() == 0) { getpid() } and a popen() process returning the same process id?

I want to know why the two process id's match when the the getpid() in the fork() to my knowledge is supposed to be a different process than the one produced by popen().
I was informed that my code only works because of what I interpret might be a bug with Ubuntu based distro's such as Xubuntu, Lubuntu, and KDE neon, (which are the distro's I've tested so far). You can easily compile and test the code from here: https://github.com/time-killer-games/XTransientFor Ignore the x64 binary available at that link if you don't trust it. Arch, RedHat, etc. testers are especially welcome to give feedback if this happens to not work for them.
Here's a much more minimal approach to demonstrating the issue:
// USAGE: xprocesstest [command]
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <unistd.h>
#include <thread>
#include <chrono>
#include <iostream>
#include <string>
using std::string;
static inline Window XGetActiveWindow(Display *display) {
unsigned long window;
unsigned char *prop;
Atom actual_type, filter_atom;
int actual_format, status;
unsigned long nitems, bytes_after;
int screen = XDefaultScreen(display);
window = RootWindow(display, screen);
filter_atom = XInternAtom(display, "_NET_ACTIVE_WINDOW", True);
status = XGetWindowProperty(display, window, filter_atom, 0, 1000, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
unsigned long long_property = prop[0] + (prop[1] << 8) + (prop[2] << 16) + (prop[3] << 24);
XFree(prop);
return (Window)long_property;
}
static inline pid_t XGetActiveProcessId(Display *display) {
unsigned long window = XGetActiveWindow(display);
unsigned char *prop;
Atom actual_type, filter_atom;
int actual_format, status;
unsigned long nitems, bytes_after;
filter_atom = XInternAtom(display, "_NET_WM_PID", True);
status = XGetWindowProperty(display, window, filter_atom, 0, 1000, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
unsigned long long_property = prop[0] + (prop[1] << 8) + (prop[2] << 16) + (prop[3] << 24);
XFree(prop);
return (pid_t)(long_property - 1);
}
int main(int argc, const char **argv) {
if (argc == 2) {
char *buffer = NULL;
size_t buffer_size = 0;
string str_buffer;
FILE *file = popen(argv[1], "r");
if (fork() == 0) {
Display *display = XOpenDisplay(NULL);
Window window;
unsigned i = 0;
while (i < 10) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
if (XGetActiveProcessId(display) == getpid()) {
window = XGetActiveWindow(display);
break;
}
i++;
}
if (window == XGetActiveWindow(display))
std::cout << "process id's match!" << std::endl;
else std::cout << "process id's don't match!" << std::endl;
XCloseDisplay(display);
exit(0);
}
while (getline(&buffer, &buffer_size, file) != -1)
str_buffer += buffer;
std::cout << str_buffer;
free(buffer);
pclose(file);
}
}
Compile with:
cd "${0%/*}"
g++ -c -std=c++17 "xprocesstest.cpp" -fPIC -m64
g++ "xprocesstest.o" -o "xprocesstest" -fPIC -lX11
Run with:
cd "${0%/*}"
./xprocesstest "kdialog --getopenfilename"
You can replace the command in the quotes with any executable which sets the _NET_WM_PID atom.
#thatotherguy explains the answer in his comment:
"Are you aware that due to your - 1 you're actually checking that the two processes have sequential pids? This is not surprising behavior on Linux. Differences between distros would be down to whether sh optimizes out the extra fork it uses to run the command"
static inline pid_t XGetActiveProcessId(Display *display) {
unsigned long window = XGetActiveWindow(display);
unsigned char *prop;
Atom actual_type, filter_atom;
int actual_format, status;
unsigned long nitems, bytes_after;
filter_atom = XInternAtom(display, "_NET_WM_PID", True);
status = XGetWindowProperty(display, window, filter_atom, 0, 1000, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
unsigned long long_property = prop[0] + (prop[1] << 8) + (prop[2] << 16) + (prop[3] << 24);
XFree(prop);
return (pid_t)(long_property - 1);
}
That - 1 in the process id return I initially added because I thought at the time it was returning the wrong process id, because I thought when I wrote that the fork() was supposed to have the same process id as the popen, which later on I discovered wasn't the case. I subtracted one, thus making two different otherwise correct process id's, incorrectly equal.
Here's the correct way to do what I intended to do, in my original code, which lead to me asking this question; I wanted to know how to detect if a fork and popen child processes stem from a common parent process (while removing the subtraction of one from the return of the GetActiveProcessId() function):
#include <proc/readproc.h>
#include <cstring>
static inline pid_t GetParentPidFromPid(pid_t pid) {
proc_t proc_info; pid_t ppid;
memset(&proc_info, 0, sizeof(proc_info));
PROCTAB *pt_ptr = openproc(PROC_FILLSTATUS | PROC_PID, &pid);
if(readproc(pt_ptr, &proc_info) != 0) {
ppid = proc_info.ppid;
string cmd = proc_info.cmd;
if (cmd == "sh")
ppid = GetParentPidFromPid(ppid);
} else ppid = 0;
closeproc(pt_ptr);
return ppid;
}
Using the above helper function, while replacing the while loop, in the original code, with this, allows me to do what I was after:
while (i < 10) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
if (GetParentPidFromPid(XGetActiveProcessId(display)) == GetParentPidFromPid(getpid()) ||
GetParentPidFromPid(GetParentPidFromPid(XGetActiveProcessId(display))) == GetParentPidFromPid(getppid())) {
window = XGetActiveWindow(display);
break;
}
i++;
}
As #thatotherguy also pointed out, some distros will return a different parent process because the sh cmd will use run directly. To solve this, I did an or check in the if statement for seeing whether the parent or "grandparent" process id's returned equal, while attempting to skip any parent processes with the sh cmd value.
The helper function needs the -lprocps linker flag and libprocps-dev package installed if you are on a Debian based system. Package name will be different on other distros.

How to know if a device has been explicitly been disabled by user?

Using device manager a user can explicitly enable/disable a device, as can be seen in the following image.
For a given device I want to know if it's currently in a user disabled/enabled state.
I have tried the following approaches
CM_Get_DevNode_Status(&status, &problem, data.DevInst, 0); I was hoping that presence of DN_STARTED, or DN_DRIVER_LOADED would tell me that. But these can be zero even when a driver is being loaded/unloaded by the OS, when the device connects/disconnects. For example, a device which is enabled, and for which driver is loaded. DN_STARTED will be 1, but when we disconnect device it is set to zero before the device's entry is removed from device manager.
SetupDiGetDeviceRegistryProperty(..., SPDRP_INSTALL_STATE, ...) I though a state of CM_INSTALL_STATE_INSTALLED should mean that the device is enabled. But the function returns this state even for disabled devices.
Using WMI I was able to get the required information, but I used wmi in PowerShell. I do not want to use wmi, as it is quite difficult to implement in native c++. I used the following query.
Select Name, Availability, ConfigManagerErrorCode, ConfigManagerUserConfig from Win32_PnPEntity where Name = 'NVIDIA Quadro M1000M'
ConfigManagerErrorCode in above query, if set to 22, means that device has been disabled, 21 means that windows is removing the device
I am looking for a non wmi solution.
The information can be obtained from a device's problem code. There are two ways which I could find to get it.
Use SetupDiGetDeviceProperty() to query DEVPKEY_Device_ProblemCode.
Use CM_Get_DevNode_Status() the problem code will be present in the second argument after the call.
A problem code of 22 (CM_PROB_DISABLED) means that the device has been explicitly disabled by a user by either using device manager, or other such utility.
Sample code
#include "stdafx.h"
#include <Windows.h>
#include <SetupAPI.h>
#include <Cfgmgr32.h>
#include <devguid.h>
#include <initguid.h>
#include "devpkey.h"
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
HDEVINFO hDevInfo = ::SetupDiGetClassDevs(&GUID_DEVCLASS_DISPLAY, NULL, NULL, 0); //only getting for GPUs on the machine
if (INVALID_HANDLE_VALUE != hDevInfo)
{
SP_DEVINFO_DATA data;
data.cbSize = (DWORD)sizeof(data);
for (unsigned int nIndex = 0; ::SetupDiEnumDeviceInfo(hDevInfo, nIndex, &data); nIndex++)
{
ULONG status = 0, problem = 0;
CONFIGRET cr = ::CM_Get_DevNode_Status(&status, &problem, data.DevInst, 0); //after the call 'problem' variable will have the problem code
if (CR_SUCCESS == cr)
{
cout << " problem " << problem <<endl;
if(problem == CM_PROB_DISABLED)
{ /*Do Something*/ }
DEVPROPTYPE propertyType;
const DWORD propertyBufferSize = 100;
BYTE propertyBuffer[propertyBufferSize];
std::fill(begin(propertyBuffer), end(propertyBuffer), BYTE(0));
DWORD requiredSize = 0;
if (SetupDiGetDeviceProperty(hDevInfo, &data, &DEVPKEY_Device_ProblemCode, &propertyType, propertyBuffer, propertyBufferSize, &requiredSize, 0)) //after the call 'propertyBuffer' will have error codes
{
unsigned long deviceProblemCode = *((unsigned long*)propertyBuffer);
cout << " deviceProblemCode " << deviceProblemCode << endl;
if(problem == CM_PROB_DISABLED)
{ /*Do Something*/ }
}
}
}
}
return 0;
}
Sample Output
problem 0
deviceProblemCode 0
problem 22
deviceProblemCode 22
In the question it can be seen that Intel(R) HD Graphics 530 was enabled, and NVIDIA Quadro M1000M was disabled. Hence in the output we got a problem code of 0, and a problem code of 22 (CM_PROB_DISABLED).

C++ - Serial (COM) port - asio | VS2015 error(s)

1. What are we trying to achieve (and why)
We're currently trying to communicate with an industrial robot over USB(COM)<->serial(RS232). We would like to control the robot from a C++ application.
2. What setup do we have
We're using Visual Studio C++ 2015 with the built-in C++ compiler. Creating a "Win32 Console Application".
3. What steps have we taken?
We've got the connection working in Processing (Java) using Serial but we would like to implement it in C++.
3.1 Boost ASIO
We're using Boost ASIO (installed with NuGet package manager).
At this point we get 2 compile errors indicating the same problem:
Error C2694 'const char *asio::detail::system_category::name(void) const': overriding virtual function has less restrictive exception specification than base class virtual member function 'const char *std::error_category::name(void) noexcept const'
I figured that this error is most likely not caused by my code (I haven't changed the library). So I believe the VS21015 C++ compiler is not fully compatible with boost::asio?
I've found two other links/posts with somewhat the same error:
https://github.com/chriskohlhoff/asio/issues/35
And I tried the following define:
#ifndef ASIO_ERROR_CATEGORY_NOEXCEPT
#define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)
#endif // !defined(ASIO_ERROR_CATEGORY_NOEXCEPT)
Error in websocketpp library and boost in windows Visual Studio 2015
With the following define:
#define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)
//or
#define ASIO_ERROR_CATEGORY_NOEXCEPT 1
But it did not resolve the errors. The even caused a lot of random syntax errors and undeclared identifiers (which would indicate missing the include of iterator.
3.2 Windows(base) and C
We've used some C code (and added in a little C++ Debugging) to detect COM ports. But it simply doesn't show them (however it does in device explorer). We even had to convert a LPCWSTR to char array (wtf?).
#include <stdio.h>
#include <cstdio>
#include <iostream>
#include <windows.h>
#include <winbase.h>
wchar_t *convertCharArrayToLPCWSTR(const char* charArray)
{
wchar_t* wString = new wchar_t[4096];
MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
return wString;
}
BOOL COM_exists(int port)
{
char buffer[7];
COMMCONFIG CommConfig;
DWORD size;
if (!(1 <= port && port <= 255))
{
return FALSE;
}
snprintf(buffer, sizeof buffer, "COM%d", port);
size = sizeof CommConfig;
// COM port exists if GetDefaultCommConfig returns TRUE
// or changes <size> to indicate COMMCONFIG buffer too small.
std::cout << "COM" << port << " | " << (GetDefaultCommConfig(convertCharArrayToLPCWSTR(buffer), &CommConfig, &size)
|| size > sizeof CommConfig) << std::endl;
return (GetDefaultCommConfig(convertCharArrayToLPCWSTR(buffer), &CommConfig, &size)
|| size > sizeof CommConfig);
}
int main()
{
int i;
for (i = 1; i < 256; ++i)
{
if (COM_exists(i))
{
printf("COM%d exists\n", i);
}
}
std::cin.get();
return 0;
}
3.3 Another Serial.h from the internet
I believe it was from: http://www.codeguru.com/cpp/i-n/network/serialcommunications/article.php/c2503/CSerial--A-C-Class-for-Serial-Communications.htm
Same rules, I include the library, everything compiles fine. (Test written below)
#include <iostream>
#include <string>
#include "Serial.h"
int main(void)
{
CSerial serial;
if (serial.Open(8, 9600))
std::cout << "Port opened successfully" << std::endl;
else
std::cout << "Failed to open port!" << std::endl;
std::cin.get();
return 0;
}
But it still doesn't show my COM ports... (They do show up in device explorer though.)
4 So what is actually working?
This particular piece of code WILL display the right COM port...
TCHAR lpTargetPath[5000]; // buffer to store the path of the COMPORTS
DWORD test;
for (int i = 0; i<255; i++) // checking ports from COM0 to COM255
{
CString str;
str.Format(_T("%d"), i);
CString ComName = CString("COM") + CString(str); // converting to COM0, COM1, COM2
test = QueryDosDevice(ComName, lpTargetPath, 5000);
// Test the return value and error if any
if (test != 0) //QueryDosDevice returns zero if it didn't find an object
{
std::cout << "COM" << i << std::endl; // add to the ComboBox
}
}
Maybe you need to update to a more recent version of boost if you have not already.
The issue with the second part is you naming of the COM port. Only COM1 to 4 can be a 'bald' name. You need to format it like this:
\\.\COM9
Clearly take care of escape sequences here:
snprintf(buffer, sizeof(buffer), "\\\\.\\COM%d", port);
EDIT: Actually you don't need to do that with GetCommConfig, only with CreateFile for opening the port. It should work. I'd suspect your conversion to wide string.
You may also find a performance enhancement of you load the cfgmgr32.dll library first.
Using CreateFile for COM port detection can result in in BSODs on some Windows systems. Particular culprits are some software modems and some bluetooth devices which show up s COM ports. So using GetDefaultCommConfig is the way to go generally though it may not work for all ports.
So what else can you do? Use setupapi.dll. Sadly this is not completely trivial..
namespace {
typedef HKEY (__stdcall *OpenDevRegKey)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM);
typedef BOOL (__stdcall *ClassGuidsFromName)(LPCTSTR, LPGUID, DWORD, PDWORD);
typedef BOOL (__stdcall *DestroyDeviceInfoList)(HDEVINFO);
typedef BOOL (__stdcall *EnumDeviceInfo)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
typedef HDEVINFO (__stdcall *GetClassDevs)(LPGUID, LPCTSTR, HWND, DWORD);
typedef BOOL (__stdcall *GetDeviceRegistryProperty)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
} // namespace
typedef std::basic_string<TCHAR> tstring;
struct PortEntry
{
tstring dev;
tstring name;
bool operator== (tstring const& device) const {
return dev == device; // TODO maybe use case-insentitive compare.
}
bool operator!= (tstring const& device) const {
return !(*this == device);
}
};
typedef std::vector<PortEntry> PortList;
// ...
DllHandler setupapi; // RAII class for LoadLibrary / FreeLibrary
if (!setupapi.load(_T("SETUPAPI.DLL"))) {
throw std::runtime_error("Can\'t open setupapi.dll");
}
OpenDevRegKey fnOpenDevRegKey =
setupapi.GetProc("SetupDiOpenDevRegKey");
ClassGuidsFromName fnClassGuidsFromName =
#ifdef UNICODE
setupapi.GetProc("SetupDiClassGuidsFromNameW");
#else
setupapi.GetProc("SetupDiClassGuidsFromNameA");
#endif
DestroyDeviceInfoList fnDestroyDeviceInfoList =
setupapi.GetProc("SetupDiDestroyDeviceInfoList");
EnumDeviceInfo fnEnumDeviceInfo =
setupapi.GetProc("SetupDiEnumDeviceInfo");
GetClassDevs fnGetClassDevs =
#ifdef UNICODE
setupapi.GetProc("SetupDiGetClassDevsW");
#else
setupapi.GetProc("SetupDiGetClassDevsA");
#endif
GetDeviceRegistryProperty fnGetDeviceRegistryProperty =
#ifdef UNICODE
setupapi.GetProc("SetupDiGetDeviceRegistryPropertyW");
#else
setupapi.GetProc("SetupDiGetDeviceRegistryPropertyA");
#endif
if ((fnOpenDevRegKey == 0) ||
(fnClassGuidsFromName == 0) ||
(fnDestroyDeviceInfoList == 0) ||
(fnEnumDeviceInfo == 0) ||
(fnGetClassDevs == 0) ||
(fnGetDeviceRegistryProperty == 0)
) {
throw std:runtime_error(
"Could not locate required functions in setupapi.dll"
);
}
// First need to get the GUID from the name "Ports"
//
DWORD dwGuids = 0;
(*fnClassGuidsFromName)(_T("Ports"), NULL, 0, &dwGuids);
if (dwGuids == 0)
{
throw std::runtime_error("Can\'t get GUIDs from \'Ports\' key in the registry");
}
// Allocate the needed memory
std::vector<GUID> guids(dwGuids);
// Get the GUIDs
if (!(*fnClassGuidsFromName)(_T("Ports"), &guids[0], dwGuids, &dwGuids))
{
throw std::runtime_error("Can\'t get GUIDs from \'Ports\' key in the registry");
}
// Now create a "device information set" which is required to enumerate all the ports
HDEVINFO hdevinfoset = (*fnGetClassDevs)(&guids[0], NULL, NULL, DIGCF_PRESENT);
if (hdevinfoset == INVALID_HANDLE_VALUE)
{
throw std::runtime_error("Can\'t get create device information set.");
}
// Finished with the guids.
guids.clear();
// Finally do the enumeration
bool more = true;
int index = 0;
SP_DEVINFO_DATA devinfo;
while (more)
{
//Enumerate the current device
devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
more = (0 != (*fnEnumDeviceInfo)(hdevinfoset, index, &devinfo));
if (more)
{
PortEntry entry;
//Did we find a serial port for this device
bool added = false;
//Get the registry key which stores the ports settings
HKEY hdevkey = (*fnOpenDevRegKey)(
hdevinfoset,
&devinfo,
DICS_FLAG_GLOBAL,
0,
DIREG_DEV,
KEY_QUERY_VALUE
);
if (hdevkey)
{
//Read in the name of the port
TCHAR port_name[256];
DWORD size = sizeof(port_name);
DWORD type = 0;
if ((::RegQueryValueEx(
hdevkey,
_T("PortName"),
NULL,
&type,
(LPBYTE) port_name,
&size
) == ERROR_SUCCESS) &&
(type == REG_SZ)
) {
// If it looks like "COMX" then
// add it to the array which will be returned
tstring s = port_name;
size_t len = s.length();
String const cmp(s, 0, 3);
if (CaseInsensitiveCompareEqual(String("COM"), cmp)) {
entry.name = s;
entry.dev = "\\\\.\\" + s;
added = true;
}
}
// Close the key now that we are finished with it
::RegCloseKey(hdevkey);
}
// If the port was a serial port, then also try to get its friendly name
if (added)
{
TCHAR friendly_name[256];
DWORD size = sizeof(friendly_name);
DWORD type = 0;
if ((fnGetDeviceRegistryProperty)(
hdevinfoset,
&devinfo,
SPDRP_DEVICEDESC,
&type,
(PBYTE)friendly_name,
size,
&size
) &&
(type == REG_SZ)
) {
entry.name += _T(" (");
entry.name += friendly_name;
entry.name += _T(")");
}
//
// Add the port to our vector.
//
// If we already have an entry for the given device, then
// overwrite it (this will add the friendly name).
//
PortList::iterator i = std::find(
ports.begin(),
ports.end(),
entry.dev
);
if (i == ports.end()) {
ports.push_back(entry);
}
else {
(*i) = entry;
}
}
}
++index;
}
// Free up the "device information set" now that we are finished with it
(*fnDestroyDeviceInfoList)(hdevinfoset);
You'll need to do a bit of work to make that compilable but it should work.
See https://support.microsoft.com/en-us/kb/259695

'SDL_main' : must return a value

I am trying to retreive content of websice in c++ usind SDL but it is giving me this error:
'SDL_main' : must return a value
my code is:
#include <iostream>
#include "SDL.h"
#include "SDL_net.h"
#include <cstring>
int main(int argc,char** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDLNet_Init();
IPaddress ip;
SDLNet_ResolveHost(&ip,"www.linux.org",80);
const char* http="GET / HTTP/1.1\nHost: www.linux.org\n\n";
TCPsocket client=SDLNet_TCP_Open(&ip);
SDLNet_TCP_Send(client,http,strlen(http)+1);
char text[10000];
while(SDLNet_TCP_Recv(client,text,10000))
std::cout << text;
SDLNet_TCP_Close(client);
SDLNet_Quit();
SDL_Quit();
}
When I put return 0; at the end, it built project but it finished immediately after that
(I am using vs2012)
UPDATE
cout<<"Some message";
doesn't print anything, is it possible that I have configured my imports wrong? are those additional dependencies right?
SDL.lib;SDL_net.lib;SDLmain.lib
I don't know what else could be wrong ...
It's because SDL defines a macro like this:
#define main SDL_main
So the function you've written is actually called SDL_main and like any other function that is not the actual main function, if it doesn't return void, you have to give it a return statement.
because your code doesn't loop forever it just returns 0 after first pass, you need to make a loop like:
while(1){
sdl_events event;
switch(event){
//handle events, drawings and so on
...
...
...
case SDL_QUIT:
exit (0);
break;
}
}
http://sdl.beuc.net/sdl.wiki/OpenGL_Full_Example
UPDATE
you may also have some problem connecting to host so you could check if connection succeed like this:
#define MAXLEN 1024
int result;
char msg[MAXLEN];
result = SDLNet_TCP_Recv(sock,msg,MAXLEN-1);
if(result <= 0) {
// TCP Connection is broken. (because of error or closure)
SDLNet_TCP_Close(sock);
exit(1);
}
else {
msg[result] = 0;
printf("Received: \"%s\"\n",msg);
}
UPDATE 2
change this:
while(SDLNet_TCP_Recv(client,text,10000))
std::cout << text;
to this:
while(SDLNet_TCP_Recv(client,text,9999))
std::cout << text;
UPDATE 3
try this, put your receive part in this if statement
if(SDLNet_SocketReady(client) == 1)
{
while(SDLNet_TCP_Recv(client,text,9999))
std::cout << text;
}
if this still doesn't work I suggest to use QT sockets or Boost asio, both async and more intuitive