problem with compiling wstring on linux with cpprestsdk - c++

I have code something like this
using namespace web;
using namespace http;
const http_response& response = /*valid assignment*/
http_headers::const_iterator it = response.headers().find(L"SomeKey");
if (it != response.headers().end())
{
//doing something
}
response is having valid data.
It is compiling with windows. I want to compile the same snippet in Linux with g++. How should I handle this?
Do I need to add some flags for compiling?
I got error like this:
error: no matching function for call to ‘web::http::http_headers::find(const wchar_t [17]) const’
http_headers::const_iterator it = response.headers().find(L"SomeKey");
^

The project use wstring for windows, string for Linux. And they provide a type string_t and a macro U to help deal with this, your code needs to be changed to be compiled both on Windows and Linux.
What is utility::string_t and the 'U' macro? The C++ REST SDK uses a
different string type dependent on the platform being targeted. For
example for the Windows platforms utility::string_t is std::wstring
using UTF-16, on Linux std::string using UTF-8. The 'U' macro can be
used to create a string literal of the platform type. If you are using
a library causing conflicts with the 'U' macro, for example
Boost.Iostreams it can be turned off by defining the macro
'_TURN_OFF_PLATFORM_STRING' before including the C++ REST SDK header
files.
See this FAQ
A tipical usage:
static const utility::string_t wl_birthday = U("wl.birthday");
static const utility::string_t wl_basic = U("wl.basic");
And for your code:
http_headers::const_iterator it = response.headers().find(U("SomeKey"));
WARN about the status of this project:
cpprestsdk is in maintenance mode and we do not recommend its use in new projects. We will continue to fix critical bugs and address security issues.

Related

Use NetCDF4-C in Unity

this is my first time posting (after lurking for years).
A project I will be tackling is to use NetCDF4 (.nc) files in Unity on Windows. I will be using Unity 5.4.0f3 and Windows 10, and I have developed in Unity before and am familiar with C# and JavaScript, but NetCDF only has C, Java, and Fortran APIs, although there are wrappers in Python, C++, and others (source: https://www.unidata.ucar.edu/publications/factsheets/current/factsheet_netcdf.pdf).
So my specific question is how do I call NetCDF4-C functions (nc_get_vara_float(), nc_open, etc) in C# for use in Unity?
What I've tried so far:
To start, I googled specifically for NetCDF4-C + Unity tutorials/attempts, but did not find anything, so instead I have been looking into the compatibility of calling C functions from C#. I am currently working on a project on Linux with NetCDF4-C and written custom wrapper functions for the netcdf.h functions, so I was hoping I could reuse my code there.
I attempted to follow this SO post (Is it possible to call a C function from C#.Net) but get an error in Unity when trying to Play: "DllNotFoundException: test.so" (my file was named "test.c"). From the comments, it seems Linux uses .so files but Windows uses .dll, and I was not sure how to generate a .dll of a C file.
I looked up another post on that (How to write a DLL file in C?) and downloaded Visual Studio to follow along. While VS was downloading, I looked up how to use GCC to compile (Creating a DLL in GCC or Cygwin?), and used the Bash subsystem ("Bash on Ubuntu on Windows" terminal) but got a handful of errors that indicated the code from the previous link (2nd SO link in this post) were for C++, so I stopped working with GCC.
Once VS finished installing, I went back to trying to use VS to create the .dll, and attempted to combine the solutions from both SO posts (1 and 2) so that I would be able to use the .dll file containing C code in Unity, but to no avail: I get the same error but just with a different extension (and different name on purpose): "DllNotFoundException: Win32Project1.dll".
The code I have is as follows:
test.cs (used in Unity and attaches to a Component):
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class test : MonoBehaviour {
[DllImport("Win32Project1.dll", EntryPoint="DisplayHelloFromMyDLL")]
public static extern void DisplayHelloFromMyDLL ();
// Use this for initialization
void Start () {
DisplayHelloFromMyDLL();
}
// Update is called once per frame
void Update () {
}
}
Win32Project1.dll (created and built in Visual Studio):
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromMyDLL()
{
printf("Hello DLL.\n");
}
}

Making code (more) cross platform

I am trying to make my (currently working on windows) code a bit more platform independent. This small snippet is for opening a text file (for reading/writing).
As with modern pcs many files are stored as unicode. Now In this question I am especially wondering what the right way to open such a file is. (Where the filename may be unicode).
On windows, using microsoft visual studio, I used
char* filename("c:\\\xD0\x92.txt");
#ifdef _WIN32
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
#else
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
//non windows wstring = utf8
#endif
std::wstring wfilename(converter.from_bytes(filename));
std::fstream fstream(wfilename);
However I just now realized this isn't standard C++11, instead a visual studio (only?) extension. However when I try on windows to first convert the widestring to an UTF-8 std::string and open the file that way the fstream doesn't recognize the filename.
So what is the cross platform solution? - Should I just expect std::fstream to always accept a widestring input? Or should I expect this on windows always?
And if possix systems don't use widestrings for their directories; what do they use?

Visual C++ code not working in Code::Blocks

I have the following code that I am currently using to call functions from a C# Dll, which works perfectly in Visual C++.
#include <mscoree.h>
#include <stdio.h>
#pragma comment(lib, "mscoree.lib")
void Bootstrap()
{
ICLRRuntimeHost *pHost = NULL;
HRESULT hr = CorBindToRuntimeEx(L"v4.0.30319", L"wks", 0, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (PVOID*)&pHost);
pHost->Start();
printf("HRESULT:%x\n", hr);
// target method MUST be static int method(string arg)
DWORD dwRet = 0;
hr = pHost->ExecuteInDefaultAppDomain(L"c:\\temp\\test.dll", L"Test.Hello", L"SayHello", L"Person!", &dwRet);
printf("HRESULT:%x\n", hr);
hr = pHost->Stop();
printf("HRESULT:%x\n", hr);
pHost->Release();
}
int main()
{
Bootstrap();
}
The problem is, when I move this into Code::Blocks (which I am more familiar with - as the little C++ I have done has been native) throws a lot of compiler errors.
The original compiler errors were because it couldn't find the header mscoree.h. I found this in the .NET SDK, so I copied it over to the mingw include directory which solved that, and then I did the same for all the other headers it couldn't find.
After copying over all the headers it then started giving a whole load of other errors, to do with the code in the headers I had just moved - nothing to do with the code below.
Why is Code::Blocks having such a hard time running this when VS runs it straight off the bat?
Thanks
Code::Blocks is a great IDE for C++ programming, but you are clearly doing Windows programming here. Though it is the same programming language, compilers are not compatible among them.
Either if you have downloaded the CodeBlocks version with the gcc compiler, or the single CodeBlocks IDE, you need to configure CodeBlocks in order to use the MS C++ compiler. In order to do that, go to Settings >> Compiler and debugger >> Toolchain executables.
Also, in the same option, look for Search directories and place there the path to the MS C++ compiler headers.
Once that is done, you will be able to compile your program.
Code::Blocks has a different compiler altogether from Visual Studio, the decoding and encoding on source code during compilation is different and cannot recognize each other though they are same programming language.

Using C++ standard streams in binary mode through Swig/Python on MinGW

I have a library written with C++ that uses standard streams to read and write objects. I also have a Python interface generated with Swig that I'm using to access the library. Everything works fine on Linux, but on Windows (on MinGW) it seems impossible to use C++ standard streams in binary mode through the Python interface. If the streams are used in text mode, the extra CR characters break the library. The standard streams are fully wrapped inside the C++ library, i.e. I'm not passing them through the Python interface.
I have tried a solution that works in C++ programs that use the library, i.e. adding the lines
#include <fcntl.h>
int _CRT_fmode = _O_BINARY;
inside the block
%{
#define SWIG_FILE_WITH_INIT
...
%}
in the Swig libfoo.i file, but it has no effect. Also adding a function
void set_binary_mode() {
assert(stdin == freopen(0, "rb", stdin));
assert(stdout == freopen(0, "wb", stdout));
}
and calling it in the beginning of the Python program seems to do nothing. Also executing in the beginning of the Python program the lines
sys.stdin = os.fdopen(sys.stdin.fileno(), 'rb', 0)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
and/or
if sys.platform == "win32":
import msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
have no effect. Any combination of the previous doesn't work either.
I'm compiling the C++ library and the Swig/Python bindings on MinGW32 (version downloaded on 20120426) on Windows XP version 2002. The versions of the tools that I'm using are Python (2.7.3), Swig (2.0.8) and gcc (4.6.2).

Determine if Linux or Windows in C++

I am writing a cross-platform compatible function in C++ that creates directories based on input filenames. I need to know if the machine is Linux or windows and use the appropriate forward or back slash. For the following code below, if the machine is Linux then isLinux = true. How do I determine the OS?
bool isLinux;
std::string slash;
std::string directoryName;
if isLinux
slash = "/";
else
slash = "\\";
end
boost::filesystem::create_directory (full_path.native_directory_string() + slash + directoryName);
Use:
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
static const std::string slash="\\";
#else
static const std::string slash="/";
#endif
BTW, you can still safely use this slash "/" on Windows as windows understands this perfectly. So just sticking with "/" slash would solve problems for all OSes even like OpenVMS where path is foo:[bar.bee]test.ext can be represented as /foo/bar/bee/test.ext.
Generally speaking, you'd have do do this with conditional compilation.
That said, if you're using boost::filesystem you should be using the portable generic path format so that you can forget about things like this.
By default, Visual Studio #defines _WIN32 in the preprocessor project settings.
So you can use
// _WIN32 = we're in windows
#ifdef _WIN32
// Windows
#else
// Not windows
#endif
Look into http://en.wikipedia.org/wiki/Uname
If you are using g++ as your compiler/GNU then you could try the code below. POSIX compliant environments support this:
#include <stdio.h>
#include <sys/utsname.h>
#include <stdlib.h>
int main()
{
struct utsname sysinfo;
if(uname(&sysinfo)) exit(9);
printf("os name: %s\n", sysinfo.sysname);
return 0;
}
One of the most used methods to do this is with a pre-processor directive. The link is for C but they're used the same way in C++. Fair warning, each compiler & OS can have their own set of directives.
predef.sourceforge.net is a comprehensive collection of all kinds of MACROs that identify compilers/operating systems and more. (linking directly to the operating system sub-site)