[Solved] How to pass parameters to a java macro from a Basic one

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
Cormic
Posts: 10
Joined: Tue Jul 16, 2024 1:50 pm

[Solved] How to pass parameters to a java macro from a Basic one

Post by Cormic »

Hi,
I have trouble calling a java macro with parameters, i.e. I don't understand what to put in the call of XScript.execute().
In the attached file, I have embedded a java class with two scripts, one with parameters and the other without.
The java code is really simple :

Code: Select all

import com.sun.star.script.provider.XScriptContext;
public class MacroJava {
    public static int getArgsCount(XScriptContext xScriptContext, Object[] args) {
        return args.length;
    }
    public static String getMessage(XScriptContext xScriptContext) {
        return "Appel OK de la macro java";
    }
}
A button in the attached document calls a macro in Basic (module1.testMacroJava) which uses the script manager to call the two java macros.
The call is successful for the java macro getMessage(), but fails for getArgsCount(). Obviously, the script manager cannot match the method signature.
I have tried many configurations for the 3 parameters of the call XScrip.invoke() without success.
I woul be grateful if somebody could give me a clue.

The parcel-descriptor is :

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<parcel language="Java" xmlns:parcel="scripting.dtd">
  <script language="Java">
    <locale lang="fr">
      <displayname value="getArgsCount"/>
      <description>
        macro java getArgsCount (avec paramètres)
      </description>
    </locale>
    <functionname value="MacroJava.getArgsCount"/>
    <logicalname value="MacroJava.getArgsCount"/>
    <languagedepprops>
        <prop name="classpath" value="TestMacroJava.jar"/>
    </languagedepprops>
  </script>
  <script language="Java">
    <locale lang="fr">
      <displayname value="getMessage"/>
      <description>
        macro java getMessage (sans paramètres)
      </description>
    </locale>
    <functionname value="MacroJava.getMessage"/>
    <logicalname value="MacroJava.getMessage"/>
    <languagedepprops>
        <prop name="classpath" value="TestMacroJava.jar"/>
    </languagedepprops>
  </script>
</parcel>
I work on Win10 pro , with LibreOffice 24.2.5.2
Sincerely
Cormic
Attachments
TestMacroJava.odt
(18.43 KiB) Downloaded 149 times
Last edited by robleyd on Fri Aug 09, 2024 12:32 am, edited 1 time in total.
Reason: Tagged [Solved]. Add green tick
LibreOffice 7.5.12 Windows 10
JeJe
Volunteer
Posts: 3127
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to pass parameters to a java macro from a Basic one

Post by JeJe »

In your document you're trying to set the aOutParamIndex and aOutParam before the call - leave these, they're filled by the script call not by you. I don't know java but it will depend of whether the parameters are one way (byval in Basic) or two way (byref in Basic)

https://www.openoffice.org/api/docs/com ... cript.html
the call would look like
bar.invoke( {"foo", "foo2", "this-is-ignored" }, aOutParamIndex, aOutParam);
and after the call the out sequences would contain

aOutParamIndex={0,2};
aOutParam={"string from a", "string from c"};

Edit: So try leaving aOutParamIndex, aOutParam as variants.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
Cormic
Posts: 10
Joined: Tue Jul 16, 2024 1:50 pm

Re: How to pass parameters to a java macro from a Basic one

Post by Cormic »

Hi JeJe, thanks for you answer.
In Java, parameters are passed by value. But when the parameter is an object, the value is a pointer to the object content, so any modification of the object is seen by the caller.
The initialization of aOutParamIndex and aOutParam in my code is just one of the (very) many configurations I have tried. I have tried letting then uninitialized, and even undeclared (as there is no Option Explicit), whithout any more success.
LibreOffice 7.5.12 Windows 10
JeJe
Volunteer
Posts: 3127
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to pass parameters to a java macro from a Basic one

Post by JeJe »

OOBasic can't handle pointers.

This says "A String in Java is actually an object"

https://www.w3schools.com/java/java_strings.asp

Have you tried the simplest case - one parameter which is a long instead of a string?
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
Cormic
Posts: 10
Joined: Tue Jul 16, 2024 1:50 pm

Re: How to pass parameters to a java macro from a Basic one

Post by Cormic »

Basic cannot handle pointers, but the ScriptManager is not written in Basic, but probably in C++ or Java, and its role is also to convert the types. So I don't think the type of the parameters can be a problem. Anyway, I have tried many things, including passing Integers and Longs.
LibreOffice 7.5.12 Windows 10
JeJe
Volunteer
Posts: 3127
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to pass parameters to a java macro from a Basic one

Post by JeJe »

Here's a simple basic example of calling a basic function, so you at least have the correct calling format.

Code: Select all


sub TestScriptInvoke
dim st as string,script,res
st    = "vnd.sun.star.script:Standard.Module1.test10?language=Basic&location=document"
script =  thiscomponent.getscriptprovider.getScript(st) 
res=script.invoke(array("stringtofirstparam","stringtosecondparam"), aOutParamIndex, aOutParam)
mri aOutParamIndex
mri aOutParam
End Sub

sub test10(byval a,byref b) 
msgbox b
end sub

You could try the LibreOffice forum in case there's someone using Java there who can help with this.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
Cormic
Posts: 10
Joined: Tue Jul 16, 2024 1:50 pm

Re: How to pass parameters to a java macro from a Basic one

Post by Cormic »

Hi JeJe, and thanks for the time you spend to help me.
Your (working) example corresponds to what I have understood for the parameters. Unfortunately, it doesn't work in my case.
I have tried :

Code: Select all

    uri    = "vnd.sun.star.script:TestMacroJava.MacroJava.getArgsCount?language=java&location=document"
    script = javaProvider.getScript(uri)
    N = script.invoke(array("stringtofirstparam","stringtosecondparam"), aOutParamIndex, aOutParam)
and I got the same exception.
I have noticed a difference with your exemple. You get the XScript interface directly with

Code: Select all

scriptProvider = thiscomponent.getscriptprovider
script =  scriptprovider.getScript(st)
This master script provider has 5 ChildNodes, among which one is a ScriptProviderForBasic and another a ScriptProviderForJava.
It appears that you can ask directly the master script provider to get a Basic macro, but not a java one, for which you have to ask specifically the ScriptProviderForJava. That seems not logical, but it's what I see. Maybe my problem comes from that difference, but I can't guess why, neither how to get the invoke call working.
LibreOffice 7.5.12 Windows 10
Cormic
Posts: 10
Joined: Tue Jul 16, 2024 1:50 pm

Re: How to pass parameters to a java macro from a Basic one

Post by Cormic »

The problem is solved ! It came from an obsolete documentation.
I used the Developer's Guide chapter 28 - Scripting Framework
https://wiki.documentfoundation.org/Doc ... ing_Macros
where it is written in "Handling arguments passed to macros"

Code: Select all

Java: The arguments are passed as an Object[] in the second parameter to the macro method

 public void handleButtonPress( XScriptContext xScriptContext, Object[] args)
 
But that's wrong now, and parameters must be declared explicitely.
With this new definition of the Java macro

Code: Select all

    public static int getArgsCount(XScriptContext xScriptContext, String[] textes, String message) {
using this Basic code

Code: Select all

	Dim textes(2), params(1), outIndex(), outParams() 
	textes(0) =  "valeur 1" : textes(1) = "valeur 2" : textes(2) = "valeur 3"
	params(0) = textes : params(1) = "message"
	uri    = "vnd.sun.star.script:TestMacroJava.MacroJava.getArgsCount?language=java&location=document"
    script = javaProvider.getScript(uri)
    N = script.invoke(params, outIndex, outParams)
it works perfectly.
LibreOffice 7.5.12 Windows 10
Cormic
Posts: 10
Joined: Tue Jul 16, 2024 1:50 pm

Re: [Solved] How to pass parameters to a java macro from a Basic one

Post by Cormic »

I was wrong saying the documentation is obsolete. It is just very incomplete and ambiguous.
Following the documentation, one's declare a Java script by

Code: Select all

public static String maMacro(XScriptContext xScriptContext, Object[] args)
This works only if the array contains at least two different types. For instance :

Code: Select all

Dim param1(2)
param1(0)=thisComponent : param1(1)="un texte" : param1(2) = 12.5
Dim params(0) : params(0) = param1
result = script.invoke(params, outIndex, outParams)
The java script receives args[0] with type "any", args[1] with type String et args[2] with type Double.
But the script will not be called if parameters have the same type.

Code: Select all

param1(0)="un texte": param1(1)="un deuxième texte" : param1(2) = "un troisième texte"]
In that case, the macro must be declared with the right type :

Code: Select all

public static String maMacro(XScriptContext xScriptContext, String[] args)
And the use of an array is not compulsory. One can use a unique parameter, but with the proper type (Object is not possible). For instance :

Code: Select all

public static String maMacro(XScriptContext xScriptContext, Double args)
can be called by :

Code: Select all

Dim D as Double : D = 12.5
Dim params(0) : params(0) = D
result = script.invoke(params, outIndex, outParams)
Passing numeric parametres that way is not really practical, for the ScriptManager doesn't consider the type delared by Dim, but only the real value of the data. That means that, if you change D = 12.5 by D = 12.0, the Script Manager will consider the data as a Byte, and the java macro will be called only if it declares the parameter by 'Byte args' (or 'Short args' or 'Long args' depending of the shortest bit number necessary to code the data). That means that the only secure way to transmit a numerical value is to put it in an array for an Objet[] parameter, and to cope with the different types received.

And last, it is possible to have as many parameters as desired in the Java prototype. For instance

Code: Select all

public static String maMacro(XScriptContext xScriptContext, String[] args1, Object[] args2, String args3, ActionEvent args4)
where all parameters must follow the above rules.
LibreOffice 7.5.12 Windows 10
Post Reply