Ask Your Question
0

Basic: pass array to native DLL

asked 2017-01-08 02:20:30 +0200

this post is marked as community wiki

This post is a wiki. Anyone with karma >75 is welcome to improve it.

In VBA an array is passed by using ByRef and passing only the first element of the array:

Declare Function foo Lib "foo" (ByRef a As Byte) As Long
Dim b(10) as Byte
b(0) = &H66
b(1) = &H6F
b(2) = &H6F
b(3) = &h0
ret = foo(b(0))

This does not work in LibreOffice Basic. Only the first byte is passed.

Declare Function foo Lib "foo (ByRef a() as Long) As Long
Dim b(3) As Long
b(0) = &H66
b(1) = &H6F
b(2) = &H6F
b(3) = &h0
ret = foo(b)

results in an error "Basic Laufzeitfehler - Objekt Variable nicht belegt" (Basic run time error - object variable not set).

How can I pass an array to a native DLL.

My LibreOffice version is 5.3 beta.

edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted
0

answered 2017-02-04 20:21:21 +0200

Lupp gravatar image

updated 2017-02-05 12:27:08 +0200

(Editing:)
Original answer deleted.
(The meaning of the term "native dll" is not obvious to me. Cf this page.)

You shouldn't need the ByRef-clause as calling by reference is default.
For LibO BASIC the calling convention cdecl (from the C++ world) seems to be mandatory (or at least default; don't know how to change).

As I tested with Declare you don't even need to associate a type (As-clause) with a parameter to pass by reference. Technically a pointer into memory will be passed which does not contain information about the type - neither about the type of elements nor about their number nor about the number and the sizes of the dimensions. If you know better, please tell me.

The code of the dll, on the other hand will contain info about the ElementType of an array to be passed as parameter. Otherwise it cannot cut it it into the pieces needed for indexed access. As long as there isn't implemented a convention (cf safeArray structure) about including this metainformation about dimensioning with the array itself (say, in the first few bytes), you will have to pass it explicitly in addition to the array reference. The byte-size of the single element, consistently specified for the array to pass/accept in BASIC and in the dll may be implicit.

A completely different thing may be the creation of com objects from registered dll. I never did it.

Now comes a rectified example:
First some BASIC code now reproducibly working

REM  *****  BASIC  *****

Option Explicit

Declare Sub doubleArray Lib "...\ArrayToDll\ArrayToDllVar.dll" Alias "doubleArray" (p1(), ByVal h0 As Long, ByVal h1 As Long)  
REM ... must be replaced with the actually correct folder path.

Function arrayTimes2(pArray)
    Dim rows As Long, columns As Long
rows = Ubound(pArray, 1) - Lbound(pArray, 1) + 1
columns = Ubound(pArray, 2) - Lbound(pArray, 2) + 1

doubleArray(pArray, rows, columns)

arrayTimes2 = pArray
End Function

Then the source of the used library (in Delphi style Pascal)

library arrayToDllVar;
{$mode objfpc}{$H+}

uses
  SysUtils, Classes;

procedure doubleArray(var pA: Array of Double; h0, h1: Longint); cdecl;
var y, x, ind : Longint;
begin
for y := 0 To h0-1 Do
    begin
    for x := 0 To h1-1 Do
        begin
        ind := y * h1 + x;
        pA[ind] := pA[ind] * 2.0;
        end;
    end;
end;

exports
doubleArray;
end.

Please let me know if you also want the compiled library and a working .ods example.

edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2017-01-08 02:20:30 +0200

Seen: 267 times

Last updated: Feb 05 '17