Ajuda em JNI! Argumentos pela linha de comando!

5 respostas
The_Pro

Pessoal vejam esse simples programa em java que chama um método nativo recebendo como parâmetro o argumento args[] da linha de comando.

public class Data{
	public static native void chamaData(String[] javaArgs);
	
	static{
		System.loadLibrary("dat");
	}
	
	public static void main(String args[]){
		Data.chamaData(args);
	}
}

Agora o programa em C usando JNI:

#include <stdio.h>
#include <stdlib.h>
#include "jni.h"
#include "Data.h"

JNIEXPORT void JNICALL Java_Data_chamaData(JNIEnv *jenv, jclass job, jobjectArray oarr){
          //Obtem o tamanho do array (argc)
          jsize argc = (*jenv)->GetArrayLength(jenv,oarr);
          //Declara um array de char para argv
          char const* argv[128];
          int i;
	  
	  jobject myObject;
	  const char *str;

          for (i=1; i < argc+1; i++){
              //Obtem cada objeto do array de objetos
              myObject = (*jenv)->GetObjectArrayElement(jenv, oarr, i-1);
              //Converte cada objeto em uma String
              str = (*jenv)->GetStringUTFChars(jenv,myObject,0);
              //Constroi o array argv
              argv[i]=str;
              printf("argv[%i] = %s\n", i, argv[i]);
          }

    //Incrementa argc para ajustar a diferença do número de argumentos entre Java e C
    argc++;

    //Com argc e argv construidos podemos escrever nosso programa
    int mes;
    char *nomemes[] = {"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho",
                    "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"};
    if (argc == 4){
             mes = atoi(argv[2]);
             if (mes<1 || mes >12)
                printf("Erro!\nUso: data dia mes ano, todos inteiros");
             else
                printf("\n%s de %s de 19%s", argv[1], nomemes[mes-1], argv[3]);
    }
    else printf("Erro!\nUso: data dia mes ano, todos inteiros");
    getchar();
    return;
}

O código funciona muito bem, como não possuía argc e argv tive que construir. Achei um tuto na net que ensinava tudo ok. O problema é que construindo argv dessa forma eu não tenho acesso a argv[0] (o nome do programa). O que eu queria mesmo era poder acessar o endereço de memória de argv[0], ou seja, &argv[0].

Nesse programa que eu coloquei eu não preciso disso, mas tou fazendo aqui outro mais complexo em que eu tenho uma função que pede &argv[0] e não sei como faço pra ter acesso a ele!

Alguma ajuda?

5 Respostas

T

Se você estiver usando Microsoft Visual Studio, pode usar a macro __argv, que está definida em <stdlib.h> .

(Ela chama uma função da “Microsoft C Run-time Library” chamada __p__argv, que retorna um char*[] contendo os argumentos passados na linha de comando do executável que carregou sua DLL JNI.

The_Pro

Thingol vc conhece alguma outra maneira de se fazer isso sem usar o Visual Studio :?: É pq tenho que implementar isso no Linux :frowning: .

T

Boa pergunta; no Linux talvez você tenha de modificar o programa C que inicia o Java, carregando a libjava.so, para que você possa obter esses parâmetros.

A propósito, por que é que você precisa de argv[0]? Normalmente, para um programa no Linux, ele é “/usr/local/bin/java” ou “/usr/local/java/bin/java” ou coisas parecidas.

O que eu faria, na verdade, é um script que passasse ao Java as coisas que você quer.

Por exemplo, digamos que você inicie seu programa Java com:

java -jar blablebli.jar parametro1 parametro2 parametro3

Escreva um script (digamos java.sh) que passe os parâmetros do jeito que você quer:

/usr/local/bin/java -jar $1 $1 $2 $3 …

(note que $1 foi repetido )

e invoque esse script como:

./java.sh seujar.jar parametro1 parametro2

O nome do jar será passado para o Java em args[0], dessa maneira você pode saber qual o nome do jar que foi usado para iniciar o programa.

The_Pro

thingol obrigado por estar ajudando! Agora ainda estou com dúvida nessa parte de criar esse script :roll: , tipo qual o código que eu coloco nesse arquivo .sh? (nunca precisei criar um arquivo desse tipo antes)

Quanto ao problema é o seguinte: tenho um programa feito em C bem extenso e complexo, só que preciso executá-lo via java (na verdade esse programa em java eu estou escrevendo e vai fazer o que esse programa em C faz e outras coisas). Reescrever esse programa em C não é algo prático ou funcional visto a sua complexidade. A saída foi usar JNI para invocá-lo. Entretanto nesse programa em C (que estava feito), tem uma funcao que recebe esses argumentos: “ex_funcao(argc, &argv[0])”, porém no momento não possuo acesso a &argv[0] por isso o programa executa mas com bugs.

Vlw!

T

Você quer saber o que é argv[0]?
Todo programa em C recebe, em argv[0], o nome do seu executável. Ele pode ser o nome completo ("/usr/bin/ls") ou o nome digitado ("ls"); depende de quem o chamou.
Se você sabe o nome completo, tudo bem. Se não souber, existe um comando no shell ("type") que indica qual é o nome completo do arquivo, dado o comando:

$ type java
java is /usr/local/java/bin/java

Para você chamar esse comando, você pode usar Runtime.exec e executar o comando “sh -c ‘type java > /tmp/type.txt’” e ler a saída que redirecionei para o arquivo /tmp/type.txt.

Criado 29 de janeiro de 2008
Ultima resposta 30 de jan. de 2008
Respostas 5
Participantes 2