Xamarin ndk从c函数获取字符串作为返回值
问题描述:
我的返回字符函数不起作用。其他人工作正常,有人可以帮助我如何从C函数获取字符串作为返回值吗?Xamarin ndk从c函数获取字符串作为返回值
我试过搜索它,但找不到解决方案。
这是我的cpp的代码
#include <android/log.h>
#include <stdio.h>
#include <string.h>
using namespace std;
extern "C" void bar_init()
{
__android_log_print (ANDROID_LOG_INFO, "*jonp*", "bar_init");
}
extern "C" int getMyName(int recept){
return recept;
}
extern "C" void PrintMyString(char const * chars){
__android_log_print (ANDROID_LOG_INFO, "*jonp*", chars);
}
extern "C" char* ReturnMyChar (char *chars){
strcpy(chars, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '')");
__android_log_print (ANDROID_LOG_INFO, "*jonp*", chars);
return chars;
}
而我的C#代码
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Runtime.InteropServices;
namespace NativeTest
{
[Activity (Label = "NativeTest", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
[DllImport ("bar.so")]
static extern void bar_init();
[DllImport ("bar.so")]
static extern int getMyName(int test);
[DllImport ("bar.so")]
static extern void PrintMyString (string myname);
[DllImport ("bar.so")]
static extern string ReturnMyChar(string mychar);
int count = 1;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
Console.WriteLine ("PREPARING");
bar_init();
int mybytes = getMyName (10);
PrintMyString ("Hello World");
Console.WriteLine ("WORKING:{0}",mybytes);
//string myValue = "hello";
string bytes = ReturnMyChar ("h");
//Console.WriteLine (myValue);
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button> (Resource.Id.myButton);
button.Click += delegate {
button.Text = string.Format ("{0} clicks!", count++);
};
}
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
static string GetString(byte[] bytes)
{
char[] chars = new char[bytes.Length/sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
}
}
这是我的日志:
[Resources] Preloaded drawable resource #0x1080093 (android:drawable/sym_def_app_icon) that varies with configuration!!
[Mono] DllImport attempting to load: '/system/lib/liblog.so'.
[Mono] DllImport loaded library '/system/lib/liblog.so'.
[Mono] DllImport searching in: '/system/lib/liblog.so' ('/system/lib/liblog.so').
[Mono] Searching for '__android_log_print'.
[Mono] Probing '__android_log_print'.
[Mono] Found as '__android_log_print'.
PREPARING
[*jonp*] bar_init
[*jonp*] Hello World
WORKING:10
[*jonp*] INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '')
[libc] invalid address or address of corrupt block 0xb7a8eee8 passed to dlfree
[mono-rt] Stacktrace:
[mono-rt]
[mono-rt] at <unknown> <0xffffffff>
找到解决方案
C代码
extern "C" char* ReturnMyChar(){
int len=strlen("INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '')")+1;
char *chars=(char*) malloc(len);
memset(chars,0,len);
strcpy(chars, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '')");
__android_log_print (ANDROID_LOG_INFO, "*jonp*", chars);
return chars;
}
C#代码
[DllImport ("bar.so")]
static extern IntPtr ReturnMyChar();
.....
IntPtr bytes = ReturnMyChar();
Console.WriteLine ("result string :"+Marshal.PtrToStringAuto(bytes));
答
按我假设你有麻烦了,因为modifying string literal in C
.
从C#
代码在调用
string bytes = ReturnMyChar ("h");
而且在C
你有接收功能
extern "C" char* ReturnMyChar (char *chars){..}
所以在这里争论变成char *chars="h"
这是常量字符串和编译器把它放在只读存储器中。所以修改它会导致未定义的行为。这里
strcpy(chars, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '')");
你有写数据在字符串文字,这会导致你的问题。
现在要解决这个问题,您必须在函数中分配内存并返回该char数组。
另外strcpy
覆盖您当前的缓冲区。所以在函数中传递字符串没有任何意义。
string bytes = ReturnMyChar ("h");//OP can you tell me
// what is purpose of passing "h"?
解决方案,但没有测试 在C
代码
extern "C" char* ReturnMyChar()
{
int len=strlen("INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '')")+1;
char *chars=malloc(len);
memset(chars,0,len);
strcpy(chars, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '')");
__android_log_print (ANDROID_LOG_INFO, "*jonp*", chars);
return chars;
}
而且从C#
你可以调用像
string bytes = ReturnMyChar();
答
改变这一行:
strcpy(chars, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '");
到:
strcpy(chars, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '')");
否则,它是一个错误的SQL语句。
您需要再次关闭支架VALUES
! 单个'
也不起作用。
您是否尝试过传递一个变量的函数,而不是一个恒定的? – Sam 2014-09-02 10:15:50