1

My return char function is not working. Others working fine, can someone help me with how to get string from C function as return value?

I've tried to search for it, but couldn't found solution.

This is my cpp code

#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;
}

And my C# code

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);
        }
    }
}

This is my log :

 [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>

Found solution

C code

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# code

[DllImport ("bar.so")]
        static extern IntPtr ReturnMyChar();

.....

IntPtr bytes = ReturnMyChar ();
            Console.WriteLine ("result string :"+Marshal.PtrToStringAuto(bytes));
munkh
  • 13
  • 1
  • 5

2 Answers2

1

Change this line:

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

to:

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

Otherwise it is an wrong SQL-Statement.

You need to close the bracket for VALUES again! Also a single ' doesn't work.

DatRid
  • 1,169
  • 2
  • 21
  • 46
  • its not about SQL i can't get string from c function as return value so i can't use my query anyway Tnx for answer – munkh Sep 02 '14 at 09:54
  • Sure? Try to correct the SQL, and then show the error please. Because at the moment the problem seems to me the SQL-Statement. And if the SQL-Statement in the C-code fails, it will break and won't return you a value. – DatRid Sep 02 '14 at 09:58
1

As per my assumption you are in trouble because of modifying string literal in C.

from your C# code you have called

string bytes = ReturnMyChar ("h");

And in C you have receive function

extern "C" char* ReturnMyChar (char *chars){..}

So here argument becomes char *chars="h" which is constant string and compiler put it in read only memory. So modifying it cause Undefined behaviour. here

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

you have write data in string literal which cause you issues.

Now to overcome this you have to allocate memory in function and return that char array.

Also strcpy overwrite your previous buffer with current one. So there is no meaning of passing string in function.

 string bytes = ReturnMyChar ("h");//OP can you tell me 
                                   // what is purpose of passing "h"?

Solution but without testing In C code

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;
}

And from C# you can call like

 string bytes = ReturnMyChar ();
Community
  • 1
  • 1
Jayesh Bhoi
  • 24,694
  • 15
  • 58
  • 73