2014-09-02 89 views
0

我的返回字符函數不起作用。其他人工作正常,有人可以幫助我如何從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)); 
+0

您是否嘗試過傳遞一個變量的函數,而不是一個恆定的? – Sam 2014-09-02 10:15:50

回答

1

按我假設你有麻煩了,因爲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(); 
+0

這看起來不錯。我不是C++程序員,所以我只是想盡我所能幫助,但你的答案是相當不錯的,也是正確的我認爲 – DatRid 2014-09-02 10:51:38

+0

@DatRid好了,你的答案也解決了一個OP問題,這對於首先解決的確很重要。這就是爲什麼已經給你+1。 – 2014-09-02 11:04:31

+0

tnx回答一點點錯誤,但它幫了我很多 – munkh 2014-09-03 01:42:57

1

改變這一行:

strcpy(chars, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '"); 

到:

strcpy(chars, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '')"); 

否則,它是一個錯誤的SQL語句。

您需要再次關閉支架VALUES! 單個'也不起作用。

+0

它不是關於SQL我不能從c函數獲取字符串作爲返回值,所以我無法使用我的查詢Tnx的答案 – munkh 2014-09-02 09:54:39

+0

當然?嘗試更正SQL,然後顯示錯誤。因爲目前這個問題在我看來是SQL語句。如果C代碼中的SQL語句失敗,它將會中斷並且不會返回值。 – DatRid 2014-09-02 09:58:40

+0

我改變了正確的查詢 – munkh 2014-09-02 10:08:20