Xamarin-ndk从c函数中获取字符串作为返回值

本文关键字:字符串 返回值 获取 函数 Xamarin-ndk | 更新日期: 2023-09-27 18:20:23

我的return char函数不起作用。其他人工作正常,有人能帮我如何从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));

Xamarin-ndk从c函数中获取字符串作为返回值

根据我的假设,由于修改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的括号!此外,单个'也不起作用。