How to cast const char* to static const char XY[]? - c++

I'm doing some C# code which is using DLLImport to call a function inside my C++ DLL:
[DllImport("my.dll", EntryPoint = "#16", CallingConvention = CallingConvention.StdCall)]
private static extern void sendstring(string s);
I call it like this in C#:
sendstring("Test1\\0test2\\0");
My C++ DLL needs to create a static const char XY[] = "Test1\0test2\0"; from this, since I need that for calling another DLLs function from inside my c++ DLL like this:
functiontootherdll(sizeof(s),(void*)s);
So my code in C++:
extern "C" {
void MyClass::sendstring( const char *s) {
functiontootherdll(sizeof(s),(void*)s);
}
The problem: It is working, if I define the thing manually inside my C++ DLL like this:
static const char Teststring[] = "Test1\0test2\0";
functiontootherdll(sizeof(Teststring),(void*)Teststring);
but it is not taking the const char *s when calling this from my C# file (it will report different errors from the called other dll).
I would need to know how I can cast the const char *s to something like static const char s[] or such.
As you realize I have little clue about all this, so any help is very welcome!

Alright, I found out a way I think:
I modified my C++ to:
extern "C" {
void MyClass::sendstring( const char *s) {
int le = strlen(s);
char p[256];
strcpy(p,s);
char XY[sizeof(p) / sizeof(*p) + 1];
int o=0;
for (int i = 0; i<le;i++) {
if (p[i] == ';') {
XY[i] = '\0';
} else {
XY[i] = p[i];
}
o++;
}
XY[o] = '\0';
functiontootherdll(sizeof(XY),(void*)XY);
}
Afterwards the function call to
functiontootherdll(sizeof(XY),(void*)XY);
is working fine.
Pls note that I send from my C# code now a string like "Test1;test2;test3;...", trying with the \\0 as separator did not work out. My call with C# is:
sendstring("Test1;test2;test3");
I don't know if this is a smart solution, but at least it is one :)

Related

String type alternative in C

I currently have a function defined in a header that looks like this
void foo::GetValue(std::string& str);
This function basically assigns a value to str. I need to come up with an alternative to str (basically, nothing that employs the standard library).
The implementation of the above function is like this in the .cpp file:
void foo::GetValue(std::string& str)
{
std::string s = bar.someMethod();
str = s;
}
I want to know what is the best/easiest option for replacing the header?
One approach I had was to replace std::string in the header file with char* so I would have this in the header:
void foo::GetValue(char* str);
And in the implementation I would have this:
void foo::GetValue(char* str)
{
std::string resp = bar.someMethod();
char* c = new char[resp.size() + 1];
std::copy(resp.begin(), resp.end(), c);
c[resp.size()] = '\0';
}
The problem with the above approach is that a lot of files are calling this function and they will need to modify their code. Also, they will need to free the above memory. Two concerns I have with this is that other callers to this function will need to do the following two things
Replace std::string being passed to the function with char*.
Free the char* when done using it.
These two items seem very costly to me to trust other callers to do.
Any suggestions on what I can do to solve this problem? Perhaps change the signature to something else? I would prefer if the caller still passes a string, however string.c_str() is a constant char pointer.
For a given C++ function like this:
std::string foo::GetValue(std::string& str)
{
return bar.someMethod(str);
}
Then your equivalent C code looks like this:
void foo_GetValue(char* str, char* res, size_t size)
{
std::string str_arg = str;
std::string result = bar.someMethod(str_arg);
strncpy(res, result.c_str(), size - 1);
res[size-1] = 0; // Ensure is NUL terminated
}
When calling from C:
void example() {
const BUFFER_LEN = 1024;
char buffer[BUFFER_LEN];
foo_GetValue("example", buffer, BUFFER_LEN);
}

convert an std::string to a Swift String

Short version:
how can I convert an std::string (object returned by a .cpp function called from a .Swift file using bridging) to a Swift String?
Long version:
I have a library written in C++ and I have to call some code using Swift. I created a bridge, adding two files in my Xcode projects:
a bridging header, which allows Swift to call C functions (afaik Swift can't call C++ functions directly, so it needs to pass through C functions)
//file bridgingHeader.h
const char * getLastOpenedFile();
and a .cpp files which can call (of course) C++ functions inside and can define C functions with extern "C"
//file wrapper.cpp
#include <string>
#include "my_library.hpp"
extern "C" const char * getStringFromLibrary()
{
const char * s = get_string_from_library().c_str();
return s;
}
I can access the return value from a .swift file using
let myString = String(cString: getStringFromLibrary())
Swift.print(myString)
Placing a breakpoint to check the value of s inside the function getStringFromLibrary() I can see the content of the string, so the function from the library is correctly called.
Anyway the .swift file prints some strange symbols and not the original string.
Changing getStringFromLibrary() to be the following
extern "C" const char * getStringFromLibrary()
{
return get_string_from_library().c_str();
}
I have as a consequence that the .swift code prints a prefix of the real string. This makes me think of a problem of memory: probably when getStringFromLibrary() exits, the std::string object returned by get_string_from_library() is destroyed, and so the memory pointed by the pointer returned with .c_str() is not reliable anymore, reason why I get wrong outputs from Swift.print().
What is the correct way to access an std::string from a .swift file and then release its memory?
You can write an Objective-C++ wrapper to work with C++ codes.
bridging header:
#include "Wrapper.hpp"
Wrapper.hpp:
#ifndef Wrapper_hpp
#define Wrapper_hpp
#import <Foundation/Foundation.h>
#if defined(__cplusplus)
extern "C" {
#endif
NSString * _Nonnull getStringFromLibrary();
#if defined(__cplusplus)
}
#endif
#endif /* Wrapper_hpp */
Wrapper.mm:
#include "Wrapper.hpp"
#include <string>
#include "my_library.hpp"
NSString * _Nonnull getStringFromLibrary() {
return [NSString stringWithUTF8String:get_string_from_library().c_str()];
}
Swift code:
print(getStringFromLibrary())
[NSString stringWithUTF8String:] copies the contents of the buffer into some internal storage and ARC manages freeing it. You have no need to define free_something().
The std::string object owns the buffer to which a pointer is returned via c_str. That means that getStringFromLibrary returns a pointer to nothing.
There are several ways you could avoid that:
1) Copy the contents of the buffer somewhere long-lived, and return a pointer to that. This usually means allocating some memory via new[] or malloc:
extern "C"
{
const char* getStringFromLibrary()
{
std::string str = get_string_from_library();
char* s = new char[str.size() + 1]{};
std::copy(str.begin(), str.end(), s);
return s;
}
void freeStringFromLibrary(char* s)
{
delete[] s;
}
}
This method is simple, but it does incur the cost of an extra copy. That may or may not be relevant depending on how big str is and how often getStringFromLibrary is called. It also requires the user to deal with resource management, so it's not particularly exception-safe.
2) Return a opaque "handle" to a std::string object and let swift access its underlying buffer and free it by different functions:
extern "C"
{
void* getStringFromLibrary()
{
std::string* s = new std::string(get_string_from_library());
return s;
}
const char* libraryGetCString(void* s)
{
return static_cast<std::string*>(s)->c_str();
}
void freeStringFromLibrary(void* s)
{
delete static_cast<std::string*>(s);
}
}
Now in swift you can do something like this:
let handle: UnsafeMutablePointer<COpaquePointer> = getStringFromLibrary()
let myString = String(cString: libraryGetCString(handle))
freeStringFromLibrary(handle)
This approach eliminates the extra copy, but it's still not exception-safe since the caller has to deal with resource management.
There's likely a way to mix Objective-C++ into the solution to avoid the issue with resource management, but sadly I'm not familiar enough with Swift or Objective-C++ to tell you what that solution looks like.
I define a function (it could be a static String extension, if you prefer):
func getStringAndFree(_ cString: UnsafePointer<Int8>) -> String {
let res = String(cString: cString)
cString.deallocate()
return res
}
and in C++,
extern "C" char *getStringFromLibrary()
{
return strdup(get_string_from_library().c_str());
}
Now in Swift, I can simply use this in a fire-and-forget way:
print("String from C++ is: " + getStringAndFree(getStringFromLibrary()))
I solved, I post the solution I ended up with.
In the future I will probably write a class which will allow me to manage the delete operation in an automatic an safer way. I will update the answer.
bridging header:
//file bridgingHeader.h
char * getStringFromLibrary();
void freeString(char * string);
wrapper:
char * std_string_to_c_string(std::string s0) {
size_t length = s0.length() + 1;
char * s1 = new char [length];
std::strcpy(s1, s0.c_str());
return s1;
}
extern "C" void freeString(char * string) {
delete [] string;
}
extern "C" char * getStringFromLibrary()
{
return std_string_to_c_string(get_string_from_library().c_str());
}
Swift code:
let c_string: UnsafeMutablePointer<Int8>! = getStringFromLibrary()
let myString = String(cString: c_string)
freeString(c_string)
Swift.print(myString)

How to pass lua string(binary) to c++ using tolua++

I hava a class likeļ¼š
class SomeClass
{
void initFromBuffer(void* buffer,int length);
void initFromString(const std::string& str);
}
Using tolua++, got the binding like:
static int SomeClass_initFromBuffer00(lua_State* tolua_S)
{
SomeClass* self = (SomeClass*) tolua_tousertype(tolua_S,1,0);
void* buffer = ((void*) tolua_touserdata(tolua_S,2,0));
int length = ((int) tolua_tonumber(tolua_S,3,0));
self->initFromBuffer(buffer,length);
}
and:
static int SomeClass_initFromString00(lua_State* tolua_S)
{
SomeClass* self = (SomeClass*) tolua_tousertype(tolua_S,1,0);
const std::string str = ((const std::string) tolua_tocppstring(tolua_S,2,0));
self->initFromString(str);
tolua_pushcppstring(tolua_S,(const char*)str);
}
Now,i want to pass binary data from lua to c++,the binary has '\0' in it,so if i use initFromString to pass it, the binary data will be trimed. But if i use initFromBuffer to pass it, i got bad ptr at `void* buffer = ((void*) tolua_touserdata(tolua_S,2,0));, the pointer is null.
So, how could i pass binary string from lua to c++?
Maybe you should stop using Tolua's bad APIs and use plain Lua's actually good APIs. Both std::string and Lua strings are capable of storing embedded null characters. The only reason tolua_tocppstring causes truncation is because the function name is a lie. It doesn't convert it to a C++ string; it converts it to a C string, a const char*.
The correct answer is to use the proper API function:
std::string fromLuaStack(lua_State *lua, int stackIx)
{
size_t len;
const char *str = lua_tolstring(lua, stackIx, &len);
return std::string(str, len);
}
Similarly, you can use lua_pushlstring to push a std::string onto the stack.
It's unfortunate that Tolua doesn't have better documentation, as there may be a function to do this all directly. If there is, I couldn't find it.

System::String reference to C++ char* parameter

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.

C++: Define simple constant for use?

In C++ I wanted to define a constant that I can use in another function, A short answer on how to do this will be fine..
Lets say at the beginning of my code I want to define this constant:
//After #includes
bool OS = 1; //1 = linux
if (OS) {
const ??? = "clear";
} else {
const ??? = "cls";
}
I don't know what type to use to define the "clear" string... I'm so confused.
Later on I want to use it within a function:
int foo() {
system(::cls); //:: for global
return 0;
}
How would I define the string up top, and use the string down below? I heard char only had one character and things... I'm not sure how to use , since it says it's converting string into const char or something.
char* isn't quite a char. char* is basically a string (it's what strings were before C++ came along).
For illustration:
int array[N]; // An array of N ints.
char str[N]; // An array of N chars, which is also (loosely) called a string.
char[] degrades to char*, so you'll often see functions take a char*.
To convert std::string to const char*, you can simply call:
std::string s;
s.c_str()
In this case, it's common to use the preprocessor to define your OS. This way you can use the compiler to do the platform specific stuff:
#ifdef OS_LINUX
const char cls[] = "clear";
#elif OS_WIN
const char cls[] = "cls";
#endif
One thing you may want to consider is making it a function. This avoids nasty dependencies of global construction order.
string GetClearCommand() {
if (OS == "LINUX") {
return "clear";
} else if (OS == "WIN") {
return "cls";
}
FAIL("No OS specified?");
return "";
}
What it looks like you're trying to do is this:
#include <iostream>
using namespace std;
#ifdef LINUX
const char cls[] = "LINUX_CLEAR";
#elif WIN
const char cls[] = "WIN_CLEAR";
#else
const char cls[] = "OTHER_CLEAR";
#endif
void fake_system(const char* arg) {
std::cout << "fake_system: " << arg << std::endl;
}
int main(int argc, char** argv) {
fake_system(cls);
return 0;
}
// Then build the program passing your OS parameter.
$ g++ -DLINUX clear.cc -o clear
$ ./clear
fake_system: LINUX_CLEAR
Here's the problem, you're suffering from going out of scope with the variables. If I declare something within brackets, it only exists within the brackets.
if( foo ){
const char* blah = "blah";
}
Once we leave the if statement, the variable blah disappears. You'll need to instantiate it non-locally to whatever brackets you write. Hence:
void Bar(){
const char* blah = "blah";
if( foo ){
//blah exists within here
}
}
However, blah will not exist outside of Bar. Get it?
Yet another option is to create a class with a bunch of static methods. Create a new method for each command. Something like:
// in sys-commands.h
class SystemCommands {
public:
static char const* clear();
static char const* remove();
};
This gives you a few nice options for the implementation. The nicest one is to have a separate implementation file for each platform that you select during compile time.
// in sys-commands-win32.cpp
#include "sys-commands.h"
char const* SystemCommands::clear() { return "cls"; }
char const* SystemCommands::remove() { return "erase /f/q"; }
// in sys-commands-macosx.cpp
#include "sys-commands.h"
char const* SystemCommands::clear() { return "/usr/bin/clear"; }
char const* SystemCommands::remove() { return "/bin/rm -fr"; }
Which file gets compiled will determine which command set will be used. Your application code will look like:
#include <cstdlib>
#include "sys-commands.h"
int main() {
std::system(SystemCommands::clear());
return 0;
}
Edit: I forgot to mention that I prefer static functions to global constants for a bunch of reasons. If nothing else, you can make them non-constant without changing their types - in other words, if you ever have to select the command set based on runtime settings, the user code does not have to change or even be aware that such a change occurred.
You can use a common header file and link to different modules depending on the systen:
// systemconstants.hpp
#ifndef SYSTEM_CONSTANTS_HPP_INCLUDED
#define SYSTEM_CONSTANTS_HPP_INCLUDED
namespace constants {
extern const char cls[]; // declaration of cls with incomplete type
}
#endif
In case of Linux, just compile and link to this one:
// linux/systemconstants.cpp
#include "systemconstants.hpp"
namespace constants {
extern const char cls[] = "clear";
}
In case of Windows, just compile and link to this one:
// windows/systemconstants.cpp
#include "systemconstants.hpp"
namespace constants {
extern const char cls[] = "cls";
}
System-specific translation units could be placed in specific subdirectories (linux/, windows/, etc) of which one could be automatically selected during the build process. This extends to many other things, not just string constants.