Page 1 of 1

Export PB functions in DLL with array input

Posted: Fri Jul 22, 2016 2:16 pm
by copperd
I am playing around with writing some functions in PB and using them in LabVIEW. I keep crashing when accessing the functions that have have arrays in the prototype.

My guess is that arrays are not handled just as pointers in PB.

Code: Select all

ProcedureDLL Maskfunction(Array Image.u(1), Array mask.a(1), Array Result.i(1),count.i)
  
  For x = 0 To count.i
    If mask.a(x) & 1 > 0
      Result.i(0) = Result.i(0) + Image.u(x)
    EndIf
    If mask.a(x) & 2 > 0
      Result.i(1) = Result.i(1) + Image.u(x)
    EndIf
    If mask.a(x) & 4 > 0
      Result.i(2) = Result.i(2) + Image.u(x)
    EndIf
    If mask.a(x) & 8 > 0
      Result.i(3) = Result.i(3) + Image.u(x)
    EndIf
    If mask.a(x) & 16 > 0
      Result.i(4) = Result.i(4) + Image.u(x)
    EndIf
    If mask.a(x) & 32 > 0
      Result.i(5) = Result.i(5) + Image.u(x)
    EndIf
    Result.i(6) = Result.i(6) + Image.u(x)
  Next
  
  
  
EndProcedure
I get the following warnings but not much to go on in terms of documentation.

[08:31:03] [COMPILER] Line 1: Warning: List, Array and Map parameters can cause issue when exported with ProcedureDLL.
[08:31:03] [COMPILER] Line 1: Warning: List, Array and Map parameters can cause issue when exported with ProcedureDLL.
[08:31:03] [COMPILER] Line 1: Warning: List, Array and Map parameters can cause issue when exported with ProcedureDLL.
[08:31:03] Compilation succeeded with 3 warning(s).

I seen the DLLsample.pb and the part about "The declaration of arrays, lists or map with Dim, NewList or NewMap must always be done inside the procedure AttachProcess." I feel I am missing some key part of information.


I seen some code here http://forums.purebasic.com/english/vie ... p?p=201276 for accessing a point as an array. Would the correct procedure be to bring in the pointer and use a structure with an array element of correct bit size set to the size?

Hmmm this works just fine. I am toying around as I write this.

Code: Select all

ProcedureDLL.i SumArray(*Array_ptr ,count.i)
  sum.i
 Structure MemoryArray
  StructureUnion
    Byte.b[0]
  EndStructureUnion
EndStructure
*Array.MemoryArray = *Array_ptr

For x = 0 To count - 1
  sum = sum + *Array\Byte[x]
Next

ProcedureReturn sum

EndProcedure
Is this the correct way to do this or a hack?

Re: Export PB functions in DLL with array input

Posted: Fri Jul 22, 2016 3:21 pm
by skywalk
Yes, pass pointers to your arrays.
Use '*myArray.Integer' instead of 'Array myArray.x(1)'.
Then assign the pointer before ProcedureReturn:
*myArray\i = @myArray()

Re: Export PB functions in DLL with array input

Posted: Fri Jul 22, 2016 6:08 pm
by copperd
Skywalk thank you for the quick reply.

This is the code I already came up with that works.

Code: Select all

ProcedureDLL Maskfunction(*Imageprt, *Maskprt, *Resultprt, count.i)
  Structure MemoryArray
    StructureUnion
      u8.a[0]
      u16.u[0]
      i64.q[0]
    EndStructureUnion
  EndStructure
  *Image.MemoryArray = *Imageprt
  *Mask.MemoryArray = *Maskprt
  *Result.MemoryArray = *Resultprt
  
  

  
  
  For x = 0 To count - 1
    If *Mask\u8[x] & 1 > 0
      *Result\i64[0] = *Result\i64[0] + *Image\u16[x]
    EndIf
    If *Mask\u8[x] & 2 > 0
      *Result\i64[1] = *Result\i64[1] + *Image\u16[x]
    EndIf
    If *Mask\u8[x] & 4 > 0
      *Result\i64[2] = *Result\i64[2] + *Image\u16[x]
    EndIf
    If *Mask\u8[x] & 8 > 0
      *Result\i64[3] = *Result\i64[3] + *Image\u16[x]
    EndIf
    If *Mask\u8[x] & 16 > 0
      *Result\i64[4] = *Result\i64[4] + *Image\u16[x]
    EndIf
    If *Mask\u8[x] & 32 > 0
      *Result\i64[5] = *Result\i64[5] + *Image\u16[x]
    EndIf
    *Result\i64[6] = *Result\i64[6] + *Image\u16[x]
  Next
  
  
  
EndProcedure
It looks like your suggesting something that might make this alittle more readable.

Re: Export PB functions in DLL with array input

Posted: Fri Jul 22, 2016 6:27 pm
by skywalk
Well, you are using a complicated construct and without bounds checks?
A more direct method would be to create global arrays in your dll with an init() procedure.
Then you can Dim/ReDim them with whatever sizing you require and reference them with the pointers I mentioned. Remember to free the arrays on dll detachprocess().

Re: Export PB functions in DLL with array input

Posted: Sat Jul 23, 2016 8:18 am
by Lunasole
skywalk wrote: Remember to free the arrays on dll detachprocess().
Is that really necessary? I didn't ever encountered any visible problems (including ones visible in process statistics - used memory, etc) while not releasing any global array or map on DLL unload


UPD: Also just added 500mb global array to one of my dlls for testing. I didn't released it in detachprocess, but anyway that used memory was properly released on DLL unload (while host-process continued to work). Bad that PB docs lack of information about this, they just saying "no, you can't" and doesn't answer why.

Re: Export PB functions in DLL with array input

Posted: Sat Jul 23, 2016 2:06 pm
by skywalk
I prefer to explicitly manage whatever memory I create. It is just habit and while modern o/s may perform these duties, it is not so much code. I've read somewhere that the o/s may retain dll memory in anticipation of repeated use. And this becomes complicated when/if the calling process crashes or hangs.

Re: Export PB functions in DLL with array input

Posted: Sat Jul 23, 2016 7:48 pm
by Lunasole
Well it all depends on HeapCreate/HeapDestroy API (on windows).
I guessed PB does FreeArray() for every array allocated on program end, but it not happens, just HeapDestroy is called as seen from dll assembly.
But it looks like all PB stuff like arrays are based on that allocated heap, so cleaned up properly without freeing them separately.

But generally you're right, it is always better to ensure. I'm just often too lazy to do such doubtful actions ^^ (as it can be time waste)