JNI: преобразование функции C в функцию в стиле Java

#java #android #c #function #pointers

#java #Android #c #функция #указатели

Вопрос:

Предыстория

Я работаю с функциями, которые передают аргументы в виде указателей. Мне нужно преобразовать функцию, написанную на C, в JAVA с тем же поведением, что и в C. Я разрабатываю для Android в Eclipse под Windows.

Пример функции C

 int testFunction( char* firstName, char* SecomdName, char* lastname, int age);
  

Эта функция принимает 3 указателя на значения char и инициализирует их, поэтому на C я могу написать что-то вроде следующего, чтобы инициализировать все три указателя:

 char* v1, v2, v3;
int res = testFunction(v1, v2, v3, 54);
  

После вызова testFunction переменные v1, v2, v3 будут инициализированы некоторыми значениями.

Пример функции JAVA

 int testFunction( String firstName, String secondName, String lastName, int age);
  

Это та же функция, что и в C, но написанная на JAVA, однако в JAVA нет указателей, что означает, что я не могу написать что-то подобное:

 String v1, v2, v3;
testFunction(v1, v2, v3, 54);
  

Вопрос:

Что я могу сделать, чтобы получить такое же поведение при инициализации для моей JAVA-функции, как в примере C? Возможно ли это?

Комментарии:

1. Ваша функция C testFunction делает не то, что вы, кажется, думаете, что она делает. Это вообще не изменяет значения v1 , v2 или v3 . Они неинициализируются перед вызовом и остаются неизменными после него.

Ответ №1:

Есть несколько вещей, которые вы могли бы сделать. Вы могли бы создать класс bean, содержащий поля, которые вы хотите создать, т. Е. Что-то вроде:

  public class Names {
     String firstName;
     String secondName;
     String lastName;
     int returnValue;

     // getters/constructors etc ommitted...
 }
  

Затем ваша тестовая функция может создать экземпляр объекта Names и вернуть его, т.Е.

  Names names = testFunction(int age);
 String firstName = names.getFirstName();
 // etc... 
  

Альтернативой, если вы имеете дело со строками, является передача через объекты StringBuilder, т.Е.

 int testFunction(StringBuilder firstName, StringBuilder secondName, StringBuilder lastName, int age) {
   // Use StringBuilder methods such as append to create the strings eg...
   firstName.append("Bob");
}
  

Тогда в другом месте вашего кода вы могли бы использовать…

 StringBuilder firstNameBuilder = new StringBuilder();
StringBuilder secondNameBuilder = new StringBuilder();
StringBuilder thirdNameBuilder = new StringBuilder();

testFunction(firstNameBuilder, secondNameBuilder, thirdNameBuilder, 84);

String firstName = firstNameBuilder.toString();  // firstName now equals "Bob"
/// etc...
  

Ответ №2:

Вам пришлось бы сделать что-то вроде этого:

 public class Person {
    public String firstName;
    public String secondName;
    public String lastName;
}

int testFunction(Person person, int age) {
    ...
    // fill person fields
}

Person person = new Person();
int res = testFunction(person, 54);
  

Ответ №3:

Вы должны применить шаблон «Holder». Грубо говоря (я не могу протестировать код прямо сейчас, но вы поймете идею), вы можете сделать что-то вроде этого:

 class Holder <T>
{
  public T element;
  public T value() { return element; }
  public void setValue(T t ) { element = t; }
}
  

а затем измените код, чтобы принимать Holder<String> элементы. У вас есть недостаток в том, что вам приходится вызывать value() (или получать внутреннюю element информацию), но это самый простой и понятный способ, который приходит мне на ум (он также используется в сопоставлении Java с IDL CORBA для хранения ссылок «out»).

Теперь вы могли бы сделать что-то вроде:

 Holder<String> name = new Holder<String>();

int result = testFunction(name, ...);
System.out.println(name.value());
  

и реализация testFunction проста:

 int testFunction(Holder<String> name, ...)
{
   name.setValue("whatever");
   // ...
}
  

Ответ №4:

Вы могли бы заставить свой testFunction(...) возвращать объект, содержащий три (примитивы char / строковые объекты).

 public MyObject testFunction(v1,v1,v3,54) {
    //do initialization stuff...
    return new MyObject(v1, v2, v3, 54);
}

public class MyObject {
    MyObject(char v1, char v2, char v3, int number) {
        // something...
    }
}