Managed c++ to clr __pin to pin_ptr or interior_ptr - c++-cli

I am trying to compile a project that was previous using /oldsyntax, but now with /clr.
std::string Jhc::Interop::stlString(System::String^ s)
{
std::string out;
const wchar_t __pin * str = PtrToStringChars(s);
int len = s->Length*4;
char *buf = new char[len];
memset(buf,len,0);
I have changed System::String *s to System::String^ s, but how do I covert the line with PtrToStringChars(s);?
I have tried using pin_ptr and interior_ptr, but cannot make it work.

Related

How do I create a std::filesystem::exists() compatible path from Windows::Storage::StorageFile? [duplicate]

I'm trying to open a file using a string parameter, however I'm getting the following error:
error C2664: 'void std::basic_ifstream<_Elem,_Traits>::open(const wchar_t *,std::ios_base::openmode,int)' : cannot convert parameter 1 from 'System::String ^' to 'const wchar_t *'
How do you convert System::String ^ to const wchar_t *?
As Hans points out, simple conversion is necessary. It would look similar to the following:
System::String ^str = L"Blah Blah";
pin_ptr<const wchar_t> convertedValue = PtrToStringChars(str); // <-- #include <vcclr.h>
const wchar_t *constValue = convertedValue; // <-- Unnecessary, but to be completely verbose
void std::basic_ifstream<_Elem, _Traits>::open(constValue, mode, i);

c and objective-c -- const char* and char*

I have a function:
-(void)ADPCMDecode:(char *)indata : (short *)outdata :(long)len {
indata is a char and the function does pointer arithmetic to iterate for a length of len, modifying outdata, which is a short and I will need to do pointer arithmetic to get the values from it.
I am attempting to call the function using:
const char *modulatedBytes1 = [modulatedAudio bytes];
char *modulatedBytes [] = modulatedBytes1;
unsigned int moduleatedLength = [modulatedAudio length];
short *decompressedBytes = NULL;
[self ADPCMDecode:modulatedBytes :decompressedBytes :moduleatedLength];
DLog(#"%hi",decompressedBytes[1]);
I get a BAD ACCESS error on this line: *outp++ = valprev; within the function, because I am passing a constant char * instead of a char *
How should I call the function, and how would I get the output from it?
I have no background in C, which is why I do not understand how to go about doing this.
Here is the C only version of the same question:
https://pastee.org/d3y3z

Give a std::string to StreamWriter to write a txt file

I want give a string as a argument to the Stream Writer writeline method in visual c++
StreamWriter^ sw = gcnew StreamWriter("Positive Sample.txt");
string Loc = "blabla";
sw->WriteLine(Loc);
It generating a error - no instance of overload function match the argument list
WriteLine method accepts CLI's String, and not std's string.
StreamWriter^ sw = gcnew StreamWriter("Positive Sample.txt");
String^ Loc = "blabla";
sw->WriteLine(Loc);
You can use System::Runtime::InteropServices::Marshal::PtrToStringAnsito marshal from C string to String, or you can pass C string into String's constructor:
string Loc = "blabla";
String^ strLoc = gcnew String(Loc.c_str());
EDIT
As Ben pointed out in the comments, you should use marshal_as instead PtrToStringAnsi:
Example from here (inverse operation could be found here)
// marshal_as_test.cpp
// compile with: /clr
#include <stdlib.h>
#include <string.h>
#include <msclr\marshal.h>
using namespace System;
using namespace msclr::interop;
int main() {
const char* message = "Test String to Marshal";
String^ result;
result = marshal_as<String^>( message );
return 0;
}

how implement function work as sprintf use wchar for parameter?

l used ANDROID NDK 。so l want to format something。just use sprintf,but l can not use it with
wchar_t. is there some helps for me?
You probably want swprintf and friends, assuming Android has it like Posix and Linux systems.
Glib (from GTK) has functions for unicode manipulation and for string utilities. I believe you should be able to make it work on Android.
In Android OS NDK versions before 5.0 ("Lollipop"), the sprintf() does not support the "%ls" (wchar_t pointer) format specifier. Thus, the following statement compiles but does not execute correctly under NDK (pre-5.0):
char buffer [1000];
wchar_t *wp = L"wide-char text";
sprintf (buffer, "My string is: %ls", wp);
The workaround is to convert the wchar_t string to UTF-8 (which is a char *) using any one of the Open Source wide-to-utf8 implementations (e.g. the UTF8-CPP project), passing its pointer to sprintf:
// WcharToUtf8: A cross-platform function I use for converting wchar_t string
// to UTF-8, based on the UTF8-CPP Open Source project
bool WcharToUtf8 (std::string &dest, const wchar_t *src, size_t srcSize)
{
bool ret = true;
dest.clear ();
size_t wideSize = sizeof (wchar_t);
if (wideSize == 2)
{
utf8::utf16to8 (src, src + srcSize, back_inserter (dest));
}
else if (wideSize == 4)
{
utf8::utf32to8 (src, src + srcSize, back_inserter (dest));
}
else
{
// sizeof (wchar_t) is not 2 or 4 (does it equal one?)! We didn't
// expect this and need to write code to handle the case.
ret = false;
}
return ret;
}
...
char buffer [1000];
wchar_t wp = L"wide-char text";
std::string utf8;
WcharToUtf8 (utf8, wp, wcslen (wp));
sprintf (buffer, "My string is: %s", utf8.c_str ());
Starting with Android 5.0 ("Lollipop"), sprintf() supports the "%ls" format specifier, so the original sprintf() code above works correctly.
If your Android NDK code needs to run on all version of Android, you should wrap all your wchar_t pointers passed to sprintf with a macro like the following:
#define CONVERTFORANDROID(e) (GetSupportsSprintfWideChar () ? (void *) e : (void *) WcharToUtf8(e).c_str ())
char buffer [1000];
wchar_t *wp = L"wide-char text";
sprintf (buffer, "My string is: %ls", CONVERTFORANDROID(wp));
The GetSupportsSprintfWideChar() function should be a local function that returns true if the running Android OS is 5.0 or above, while returning false if the OS is pre-5.0.

LdrLoadDll problem

I am trying to code an alternative to LoadLibrary function, based on the idea of calling the function LdrLoadDll from ntdll.
This function needs as a parameter the dll file to load, in a UNICODE_STRING format.
I really can't get what I am doing wrong here (string seems to be correctly initialized), but when LdrLoadDll is called, I get the following error:
Unhandled exception in "Test.exe" (NTDLL.DLL): 0xC0000005: Access Violation.
I use Visual C++ 6.0 for this test, and I am using Windows 7 64 bit.
I post full code here, thanks in advance for any help:
#include <Windows.h>
typedef LONG NTSTATUS; //To be used with VC++ 6, since NTSTATUS type is not defined
typedef struct _UNICODE_STRING { //UNICODE_STRING structure
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef NTSTATUS (WINAPI *fLdrLoadDll) //LdrLoadDll function prototype
(
IN PWCHAR PathToFile OPTIONAL,
IN ULONG Flags OPTIONAL,
IN PUNICODE_STRING ModuleFileName,
OUT PHANDLE ModuleHandle
);
/**************************************************************************
* RtlInitUnicodeString (NTDLL.#)
*
* Initializes a buffered unicode string.
*
* RETURNS
* Nothing.
*
* NOTES
* Assigns source to target->Buffer. The length of source is assigned to
* target->Length and target->MaximumLength. If source is NULL the length
* of source is assumed to be 0.
*/
void WINAPI RtlInitUnicodeString(
PUNICODE_STRING target, /* [I/O] Buffered unicode string to be initialized */
PCWSTR source) /* [I] '\0' terminated unicode string used to initialize target */
{
if ((target->Buffer = (PWSTR) source))
{
unsigned int length = lstrlenW(source) * sizeof(WCHAR);
if (length > 0xfffc)
length = 0xfffc;
target->Length = length;
target->MaximumLength = target->Length + sizeof(WCHAR);
}
else target->Length = target->MaximumLength = 0;
}
NTSTATUS LoadDll( LPCSTR lpFileName)
{
HMODULE hmodule = GetModuleHandleA("ntdll.dll");
fLdrLoadDll _LdrLoadDll = (fLdrLoadDll) GetProcAddress ( hmodule, "LdrLoadDll" );
int AnsiLen = lstrlenA(lpFileName);
BSTR WideStr = SysAllocStringLen(NULL, AnsiLen);
::MultiByteToWideChar(CP_ACP, 0, lpFileName, AnsiLen, WideStr, AnsiLen);
UNICODE_STRING usDllFile;
RtlInitUnicodeString(&usDllFile, WideStr); //Initialize UNICODE_STRING for LdrLoadDll function
::SysFreeString(WideStr);
NTSTATUS result = _LdrLoadDll(NULL, LOAD_WITH_ALTERED_SEARCH_PATH, &usDllFile,0); //Error on this line!
return result;
}
void main()
{
LoadDll("Kernel32.dll");
}
in
_LdrLoadDll(NULL, LOAD_WITH_ALTERED_SEARCH_PATH, &usDllFile,0);
last parameter can't be zero
you can't call SysFreeString before you call _LdrLoadDll,
since the usDllFile.buffer parameter points to this string