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 1
s 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 1
s 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
Is There a Faster Way to Scan Through a Directory Recursively in .Net
How Does Wcf Deserialization Instantiate Objects Without Calling a Constructor
Grid Lines Are Not Displaying in Grid View
Simple iOS Bluetooth Data Transmission Using Unity
Where Does Error Cs0433 "Type 'X' Already Exists in Both A.Dll and B.Dll " Come From
Data Binding in Wpf User Controls
Sqldataadapter VS SQLdatareader
Opening a Folder in Explorer and Selecting a File
How to Style Chat Window Using CSS When Using Microsoft Bot Framework
Executing R Script Programmatically
Making a Private Method Public to Unit Test It...Good Idea
Add "Everyone" Privilege to Folder Using C#.Net