How to pass structure variable to DLL

DaveW

Active Member
Licensed User
Longtime User
I am trying to port the more processor intensive portions of my program to DLLs to speed the operations up. I have succeeded with some image based processes and would like to do some based on structure variables. However I have no idea how I can pass a structure variable that is defined in B4PPC to a C# function in a DLL. I am sure it must be possible - but how?!

If for example I have:

B4X:
Sub Globals
            Dim Type(Name, ID, Age) person
End Sub

how can I create a B4PPC procedure:
B4X:
            MyProc(person)

that links to:
B4X:
            public void MyProc(some_struct_name aperson)
David.
 

agraham

Expert
Licensed User
Longtime User
Like this, as an array

B4X:
Sub Globals
  Dim Type(Name, ID, Age) person ' default type is String
  Dim Type(Name, ID, Age persons(2) ' 2D array
  Dim Type (X, Y) points(10,10) As Int32 ' typed 3D array
  Dim array3D (10,10,10) As Double ' another typed 3D array
End Sub

' B4PPC procedures:
Lib.MyProc(person())

Lib.AnotherProc(persons())

Lib.YetAnotherProc(points())

Lib.LastProc(array3D())


' library methods:
public void MyProc(String[] aperson)

public void AnotherProc(String[,] somepersons)

public void YetAnotherProc(Int32[,,] somepoints)

public void Last(Double[,,] a3Darray)
 

DaveW

Active Member
Licensed User
Longtime User
Thinking about it some more.... Once I get the structure variable in the method, do I have to treat it as an array of strings? So in B4PPC I can reference Person.Age but in the DLL method would it have to be Person[2] ?
 

DaveW

Active Member
Licensed User
Longtime User
:sign0148: That's going to be fun - I have 24 fields in my structure to keep straight :(
 

DaveW

Active Member
Licensed User
Longtime User
Look up "enum" in your C# docs.
I think my C# docs will have to be a Christmas present ;)
Any recommendations for a good C# book?
 

agraham

Expert
Licensed User
Longtime User
Any recommendations for a good C# book?
My bible is "The Complete Reference to C# 2.0 by Herb Schildt", Osborne, ISBN 0-07-2266209-5. I don't know where you are based but anyone in the UK should check out The Book Depository if they don't already know about them. I've bought a lot of stuff from them.
 

DaveW

Active Member
Licensed User
Longtime User
Hi Andrew,

I have got the DLL working except for one small (really big) problem. I have to redim the structures/arrays inside the function to take the data I am reading in from an XML file. I can do the redim OK and I can read the data - debugging messages in the DLL show that they are the right size and full of data when the function finishes. However when the function returns to B4PPC the structures are all empty. Another structure/array that does not get redimed does return it's data OK so I know some of it is working. Could it be that the redim is breaking the link to the passed structure in some way? Do you have any suggestions to get over this problem?

Regards,
David.
 

agraham

Expert
Licensed User
Longtime User
Could it be that the redim is breaking the link to the passed structure in some way? Do you have any suggestions to get over this problem?
It almost certainly is (arrays are reference types - read your new book :) ) and I'm sure there is a solution but some of your explanation is bit too fuzzy to let me understand what is happening I'm afraid. Is the "function" within Basic4ppc or the library and by ReDim do you mean a Basic4pcc Dim in a Sub or a C# "array = new somtetype[somesize];"

If you post the code for the library function and the Basic4ppc code line that you use to call it I'll sort it for you.
 

DaveW

Active Member
Licensed User
Longtime User
Sorry, still waiting for Father Christmas to visit ;)

Code is:

in B4PPC
B4X:
'global
Public CompBaseData(0,0) As single

'sub
xmlread.OpenComp(name,main.CompInfo(),CompBaseData())

in DLL
B4X:
public void OpenComp(String filename, string[] CompInfo, float[,] CompBaseData)
.....
// this bit resizes the structure/array
float[,] temp = new float[Cols,Rows];
System.Array.Copy(CompBaseData,temp,CompBaseData.Length);
CompBaseData = temp;
//remaining code fills the array with data (works within the function)

I hope that this is more understandable :)
 

agraham

Expert
Licensed User
Longtime User
I hope that this is more understandable
Yup, it is. The library gets passed a reference to the array, effectively its address in memory, in a local parameter variable held on the call stack. Using this reference you can update the data as seen by Basic4ppc as you both hold the same reference. By reassigning the library parameter variable that holds the reference you are assigning a new reference to a new array in a different area of memory to a local variable on the stack which gets lost when the method returns. You need to pass that new reference back to Basic4ppc and assign it to an array variable for it to be able to use it.


B4X:
'global
Public CompBaseData(0,0) As single

'sub
CompBaseData() = xmlread.OpenComp(name,main.CompInfo(),CompBaseData())

public void OpenComp(String filename, string[] CompInfo, float[,] CompBaseData)
.....
// this bit resizes the structure/array
float[,] temp = new float[Cols,Rows];
System.Array.Copy(CompBaseData,temp,CompBaseData.Length);
  ...
return temp;
 

DaveW

Active Member
Licensed User
Longtime User
I'm afraid that there is a bit more complication - there are actually 4 structures that get passed and resized (I only showed one for clarity). I would need do something like:

Return temp1, temp2, temp3, temp4;

but that won't work either of course as there can only be one return value :(
 

agraham

Expert
Licensed User
Longtime User
there are actually 4 structures that get passed and resized (I only showed one for clarity
I expected you to come back with that one :) Use some globals in the library and return the array references with properties.

B4X:
Basic4Ppc
Dim Array1 etc
...

Library.myfunc(stuff)
Array1 = Library.Array1
 etc.


DLL

private float[,] array1;
private float[,] array2;
private float[,] array2;


public void myfunc(stuff)
{
  array1 = new float[da-da]
  array2 = etc.
   do stuff
}

public float[,] Array1
{ get { return array1; } }

etc.
 

DaveW

Active Member
Licensed User
Longtime User
I cheated - and took my usual crude but effective approach. I split the DLL function into 2, one to just get the size data, resized the structures in B4PPC and then read the data into the correctly sized arrays in a second function. It works and in combination with the ArrayToImage function, cuts the process time from 233 seconds to 30 seconds! :sign0060:

I will try to use your more elegant solution though.

Thanks for all the support! :sign0098:
 
Top