How to Return Text from Native (C++) Code

How to return text from Native (C++) code

I'd do it with a BSTR since it means you don't have to call into native twice per string, once to get the length and then once to get the contents.

With a BSTR the marshaller will take care of deallocating the BSTR with the right memory manager so you can safely pass it out of your C++ code.

C++

#include <comutil.h>
BSTR GetSomeText()
{
return ::SysAllocString(L"Greetings from the native world!");
}

C#

[DllImport(@"test.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string GetSomeText();

There is one minor drawback of the BSTR, namely that it carries a UTF-16 payload but your source data may well be char*.

To overcome this you can wrap up the conversion from char* to BSTR like this:

BSTR ANSItoBSTR(const char* input)
{
BSTR result = NULL;
int lenA = lstrlenA(input);
int lenW = ::MultiByteToWideChar(CP_ACP, 0, input, lenA, NULL, 0);
if (lenW > 0)
{
result = ::SysAllocStringLen(0, lenW);
::MultiByteToWideChar(CP_ACP, 0, input, lenA, result, lenW);
}
return result;
}

That's the hardest one out of the way, and now it's easy to add other wrappers to convert to BSTR from LPWSTR, std::string, std::wstring etc.

How to set the text in a TextBox control from native code?

The "native" way of setting the text on a textbox is to send the textbox the WM_SETTEXT message:

// handle is initialized from TextBox::Handle
PostMessage(handle, WM_SETTEXT, 0, _T("Some text"));

Read up on PostMessage and SendMessage, too. Depending on how you allocate and build up the text, you may need to use SendMessage to avoid deallocating prematurely.

JNI: Reading a text file in C code and returning to sdk

Try this:

JNIEXPORT jstring JNICALL Java_com_example_openfile_MainActivity_ndkopenfile
(JNIEnv *env, jobject this)
{
char myStr[20];
FILE* fp = fopen("/sdcard/x.txt","w+");
if(fp!=NULL)
{
fgets(myStr,20,fp);
fflush(fp);
fclose(fp);
return(*env)->NewStringUTF(env,myStr);
}
else
{
fclose(fp);
return(*env)->NewStringUTF(env,"Error opening file!");
}
}

This technique works perfectly !!! Tested.

Return data from native method via pointer in .NET

It all boils down to the contract of the function that you are trying to call, which you have not told us much about: Is it supposed to return a character, a byte, a bit, a boolean?

You should have expected chr(48) and chr(49) if the function you are calling was supposed to return a character. But obviously, you are not receiving one. Pay no attention to the fact that char is used internally: char is used in old-style C code in place of byte, bit and boolean. So, you have to have some kind of spec to follow, instead of trying to do a literal reading of the internals of some other guy's code.

In the C family of languages, the if() statement checks whether something is zero (FALSE) or non-zero (TRUE). As a result, when something is supposed to evaluate to TRUE, it is not necessary that it be equal to 1, it can be any non-zero value. And actually, -1 is not uncommon.

A bit pattern of all 1s is a non-zero value, so if it is examined as a boolean, it corresponds to TRUE. (And in two's complement a bit pattern of all 1s is actually -1.) So, it is quite possible that the function you are calling is supposed to return a boolean value, and you are in fact receiving a TRUE.

(Of course, in light of this, code like if( u1Val == 1 ) is kind of weird, it ought to have been if( u1Val != 0 ), so there may be something fishy going on.)

Returning an int from native function(c++, jni) crashes application

jint Java_org_ntorrent_DummyTorrentInfoProvider_next(
JNIEnv * env, jobject obj, jint number)

and

public native Integer next(Integer number);

Do not match. An Integer is an Object, while an int is a primitive.

If your native code uses jint, your java code should use int in the declaration of the native method.

(If you wish to pass an Integer, you'll need to treat it as a jobject on the native side, and jump through hoops to access it - it's probably easier to use int/jint and do any necessary conversion to from Integer in the java side)

Why can't I return a char* string from C++ to C# in a Release build?

Or maybe try to use

[DllImport("SimpleDll")]
public static extern IntPtr ReturnString();

and in your calling code, use the Marshal Class

string ret = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(PInvoke.ReturnString());

#include a text file in a C program as a char[]

I'd suggest using (unix util)xxd for this.
you can use it like so

$ echo hello world > a
$ xxd -i a

outputs:

unsigned char a[] = {
0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a
};
unsigned int a_len = 12;

PInvoke: Error in returing text from C++ to C#

I guess the problem is that you are allocating memory with your C++ runtime's allocator but then the C# marshaller attempts to deallocate it. That cannot work. You need to allocate and deallocate with the same allocator.

The best way I know to solve your problem is to marshal with a BSTR. That uses the COM allocator which is happy to be shared between native and managed modules.

#include <comutil.h>
BSTR cppReturnSomeText()
{
UnicodeString usText("Some Text Here");
std::wstring result = ECUtilsICU::UniCodeStringToWString(usText);
return ::SysAllocString(result.c_str());
}

On the C# side you do this:

[DllImport(MY_DLL_NAME, CallingConvention=CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string cppReturnSomeText();

One other benefit of this is that your code is now thread-safe because you no longer need a global variable.



Related Topics



Leave a reply



Submit