Modify Array VB & PB with a DLL, please need help please :-(

Just starting out? Need help? Post your questions and find answers here.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Modify Array VB & PB with a DLL, please need help please :-(

Post by Kwai chang caine »

Hello at all

KCC dream to passing an string array VB or PB in DLL, and modify it into a DLL for return in VB or PB
This job seem simple in the first see...but KCC eat several box of sedative for sleep, since he have begin this code :?

Despite that several help of SROD, IDLE, CPLBATOR, XOMBIE, GEBONET and perhaps other that i thanks again all 8) .
This time and the first time since 4 years...KCC walk on the same place and tourn around :(
The more strong is obviously VB :?
With his BSTR array :evil:

So with the precious help of SROD, KCC retry one of his method and probably the best and more simple.
The passing of pointers of array.

So i follow the advice of my master :D
KCC begin at the beginning, and restart at zero.
It's the more simple.....
And oouuuinnnnn arrreeeuuu !!!! arrreeuuuuu oouuuinnnnn arreeeuu !!!!
Huummmm Huummmm !!! perhaps KCC have beginning a little bit too much at zero :roll: :lol:

So i say after several years.....And i try to move step by step, like this, you can help KCC if you want, before that the code is too complex to read :D
It's a little bit like if KCC open a association "save willy" but here it's "save KCC" :lol:

Like the most hard is the passing VB/DLL i begin by that :roll:
KCC have rewrite a piece of VB and PB code for passing the BSTR array VB at the DLL
That's works.....
For a better understanding, KCC have translate all his functions in english :wink:

VB code

Code: Select all

Private Declare Function ModifyArray Lib "DLLArray.dll" (PointerArray As Long) As Long

Private Sub Form_Load()
 
 Dim ArrayString(10) As String
 ArrayString(0) = Trim(Str(UBound(ArrayString)))
 
 For i = 1 To 10
  ArrayString(i) = "Sentence " + Str(i)
 Next
 
 Dim AdresseArrayPointers() As Long
 AdresseArrayPointers = ArrayString2ArrayPointer(ArrayString)
 ModifyArray AdresseArrayPointers(0)
 
End Sub

Public Function ArrayString2ArrayPointer(ArrayString() As String) As Variant
 
 Dim MaxArray As Integer, ArrayPointer() As Long
 MaxArray = UBound(ArrayString)
 ReDim ArrayPointer(MaxArray) As Long
 ArrayPointer(0) = MaxArray
 
 For i = 1 To MaxArray
  ArrayPointer(i) = StrPtr(ArrayString(i))
 Next

 ArrayString2ArrayPointer = ArrayPointer
 
End Function
Code of the DLL

Code: Select all

Procedure ArrayBstr2Ansi(*AdresseTabloBSTR)
 
 SizeOfArray.l = PeekL(*AdresseTabloBSTR)
 Dim ArrayPointersInfoSoft(SizeOfArray)
 Static Dim ArrayANSI.s(1000)
 CopyMemory(*AdresseTabloBSTR + 4, @ArrayPointersInfoSoft(), SizeOfArray * 4)
  
 For i = 0 To SizeOfArray - 1
  
  If ArrayPointersInfoSoft(i) <> 0  
 
   *BSTR = ArrayPointersInfoSoft(i)
   lenBSTR = PeekL(*BSTR - 4) / 2 
   Dim Char.c(lenBSTR) 
   
   For u = 0 To lenBSTR 
    Char(u) = PeekC(*BSTR + u * 2) 
   Next
   
   ArrayANSI(i + 1) = PeekS(@Char(0))

  Else
   
   ArrayANSI(i + 1) = " " 
   
  EndIf

 Next
 
 ReDim ArrayANSI(i)
 ProcedureReturn ArrayANSI()
 
EndProcedure

ProcedureDLL ModifyArray(*PointerArray)
 
 Static Dim ArrayANSI.s(0)
 ArrayANSI() = ArrayBstr2Ansi(*PointerArray)
      
 For i = 1 To ArraySize(ArrayANSI())
  TabloVB$ + ArrayANSI(i) + Chr(13)
 Next
 
 MessageRequester("Try", TabloVB$)
 
EndProcedure
And now...it's here that the things is most complex...the modify and return to VB....
I continue to search

Tanks to have read up till here 8)
Good day at all
Last edited by Kwai chang caine on Thu Oct 01, 2009 11:31 am, edited 2 times in total.
ImageThe happiness is a road...
Not a destination
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by srod »

The following works fine here :

VB Code :

Code: Select all

Private Declare Function ListStrings Lib "test.dll" (ByVal PointerArray As Long, Number As Integer) As Long
 
Private Sub Form_Load()
 
 Dim ArrayString(10) As String
 ArrayString(0) = Trim(Str(UBound(ArrayString)))
 
 For i = 1 To 10
  ArrayString(i) = "Sentence " + Str(i)
 Next
 
 ListStrings VarPtr(ArrayString(0))
End Sub

Purebasic dll code :

Code: Select all

ProcedureDLL ListStrings(*strPtr.INTEGER, Number)
  numElements = Val(PeekS(*strPtr\i, -1, #PB_Unicode))
  MessageRequester("Array from VB", "Number of elements = " + Str(numElements))
  For i = 1 To numElements
    *strPtr + SizeOf(INTEGER)
    text$ + "Element " + Str(i) + " = " + PeekS(*strPtr\i, -1, #PB_Unicode) + #CRLF$
  Next
  MessageRequester("Array from VB", text$)
EndProcedure
The PB code could be made easier if you were compiling a Unicoded program.

I wouldn't use this to modify the strings though. You'd likely end up with a crash if you did that.
I may look like a mule, but I'm not a complete ass.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by Kwai chang caine »

Thank you very much SROD
Obviously your code is much short 8)

1/ The first step is optimized by you now 8)
The array of VB is in PB.....

2/ The second step is modify it
3/ The third step is return it in VB
Srod wrote:I wouldn't use this to modify the strings though. You'd likely end up with a crash if you did that.
If i have good understand...it's impossible to modify the array in the DLL and return the array in VB ??? :shock: :(
ImageThe happiness is a road...
Not a destination
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by srod »

If i have good understand...it's impossible to modify the array in the DLL and return the array in VB ???
I have tried saying that to you in at least 4 separate threads now! What you are attempting to do is very very risky - and completely nuts!

I can't put it any clearer than that.

Now, having said that - nothing is impossible. Why don't you have VB just shove the strings into a large buffer, get the dll to modify the buffer and then have VB copy the strings back! What is the problem? It is safe.

Attempting to modify a string array 'in place' is risky unless you are absolutely certain that you will not be writing back any strings which are longer than the original strings etc. I don't know enough about how VB allocates the memory for it's array strings and so can not be any more specific.
I may look like a mule, but I'm not a complete ass.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by Kwai chang caine »

Ok ok....if you say that...that it's right :?
You don't must be angry against KCC
You understand at the light speed...but the brain of KCC is always in the dark :(
For send the VB example....one hour for me to code and again i'm happy...for you one minute......
It's just to be sure of understand....i'm not a mule for nothing :roll:

I have nothing against memory transfert...i want just transfert the array by any way possible, memory, pipe, mutex, phone, fax...no no....not phone or fax :D
Remember my POST
http://www.purebasic.fr/english/viewtop ... 76&start=0

I have talk to you of memory transfert of VB....
I have believe it's impossible, but yes it's possible....

But obviously it's possible by you, NETMAESTRO, SPARKIE, TSSOFT, KIFFY, FLUIDBYTE, etc ....but not by KCC :(
In this thread I have try to read the memory allowed by VB...and nothing sing :(

Can you mix your splendid, short code, with the code of the link above for return the array , please :D
Like this KCC can close the "cold case" EXE/DLL array transfert :lol:

SROD my life is in your hands....so i want say...in your brain and fingers... :roll:
So if you can't help me...i don't want that you are angry against KCC.
I prefer your laugh....what you are already do for your floor clothe is already so much....

But you know that.. a man more he can't do anything.....more he ask the impossible :oops:
ImageThe happiness is a road...
Not a destination
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by srod »

Kwai, I am not angry - a little frustrated about going around in circles perhaps.

The code by Stefan Savev is of no use whatsoever; it doesn't do anything other than copy one variable to another via some heap memory.

Look, if you must pass a string array from VB to a PB dll and have the dll modify the strings in that array then you (as I have said repeatedly) have several options. I cannot write the code for you because I do not have VB 6 installed and have no intention of installing it. My code above shows how the PB dll can directly access a string array from VB. Whether you choose to poke new strings into the underlying memory buffers is up to you, but you can expect crashes if you try that.

Option 1.
Get inside VB and figure out (or go ask on a VB forum) how the memory for the array strings are allocated? If they are system allocated BSTRs then we can free them and replace them with our own Unicode strings without a problem. E.g. if the array is actually a SafeArray then we have no problems. Otherwise, select another option!

Option 2.
Pass the string array as with my above code. The dll then creates a HUGE BSTR containing delimited copies of the modified strings (the original string array is not touched). Pass a pointer to this BSTR back to VB which can then separate the new strings and copy them to the original array. VB then frees the BSTR passed by the dll with SysFreeString_().

A barmy plan, but one that should work and without any risk of crashes.

Option 3.
Use an array of fixed length strings (as opposed to dynamic ones)! I assume VB can do this? Your dll can then over-write these strings without worrying about dynamic memory allocation and who frees what? Course you need to then impose a maximum length on each string, but this method is perhaps the simplest one.

There are a million and one variations of these options you could opt for.
I may look like a mule, but I'm not a complete ass.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by Kwai chang caine »

I'm happy you are not angry :D
It's difficult to see when someone is angry in a forum :roll:
And KCC just search a solution....don't want disturb anyone :(

KCC have always hungry....in the real life...but also in programming
In the life KCC have a good refrigerator...and a good cooker wife :D
So in programming ....KCC have just you, books and all the kinds programmers of the forums, who want help him 8)
Because KCC is workman, not go so much at shool :oops:
KCC read, search everywhere in the forum VB, PB and the web
But sometime the mission is impossible for KCC, and KCC is not tom cruise :(

So you have good explain to KCC
The option 2 is interesting :D
That the first i try....

But now i must find VB code who read in memory all that PB put inside :roll:
This is the new mission of KCC :?

Thanks SROD...KCC must go to paris today
But then he return.....he search a solution.

If the fishing is good....KCC shared the fish with his master..... i promise you :D
I hope you like fish ???? :D
Other KCC perhaps found patatoes in the VB forum :roll:

Again thanks for all 8)
ImageThe happiness is a road...
Not a destination
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by srod »

Okay option 2... SET THE UNICODE SWITCH! This is a UNICODE dll. We will need to make adjustments if you want an ansi dll.

Code: Select all

ProcedureDLL.i ListStrings(*strPtr.STRING)
  Protected text$, numElements, i, bstr
  numElements = Val(*strPtr\s)
  For i = 1 To numElements
    *strPtr + SizeOf(STRING)
    text$ + *strPtr\s + Chr(1)
  Next
  bstr = SysAllocString_(@text$)
  ProcedureReturn bstr
EndProcedure
Note that I have removed the second parameter from the dll function (which you called number). I have used a Chr(1) separator but you can use whatever separator you want. I have tested this code with the VB exe you sent me and it accesses the strings from the VB array fine. You will now need to alter your VB code to accept the BSTR return - grab the contents of the string (using some VB code - the equivalent of PeekS() or use some pointer or other), separate the string and then copy them back to the original array. Finally, use the SysFreeString() api function (which you will need to import into your VB application from oleaut32.dll) to free the BSTR retrieved from the dll.

Simple! :)
I may look like a mule, but I'm not a complete ass.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by Kwai chang caine »

My einstein master srod wrote:Okay option 2... SET THE UNICODE SWITCH! This is a UNICODE dll. We will need to make adjustments if you want an ansi dll.

(W2 * UI / G²) - Mp@ * [jkl] #g =LM = SROD (56 *2) - VB => sDrf{122} KCC 258 (L/ghjh/)

Simple! :)
:shock:
:( :) :D :lol: :lol: :lol: :lol:
I love your humor..... :lol:
Really i love..all is so simple with you....
I'm sure you don't use the handle for open a door in your home...just with the brain :D

So good....KCC is a "winner" a little but ......
KCC want to make proud his master :?
Then KCC works hard when he return of PARIS because no PC in PARIS :(

Thanks thanks thanks 8)

I believe, that the dream team, eat a lot of fish and patatoes soon :lol:
ImageThe happiness is a road...
Not a destination
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by Kwai chang caine »

Helllooo :D

Kcc's back from paris.
But he don't love it :(
KCC is workman....and is lost in this big town :(

So now, the first thing KCC do, it's continue the story of DLL/VB/PB transfert
Obviously..that's don't works (We don't change a team who loose all the time :oops:)

I have modify the PB code for use VB and PB in the same procedure
I have try to return the memory in VB, but i have hieroglyph :(

So i take the problems one by one
When i call the DLL by PB, i have this result :shock:
If somebody know why ???
Sentence 1|)Sentence 2|Sentence 3|
The two square is writing "STX" and "ACK" in the PB IDE :shock:

Code of DLL

Code: Select all

ProcedureDLL ListStrings(*strPtr.INTEGER, Number)
 
 #ArrayPB = 1
 #ArrayVB = 2
 
 NumElements = Val(PeekS(*strPtr\i, -1, #PB_Unicode))
 TypeArray = #ArrayVB
 
 If Not NumElements
  NumElements = Val(PeekS(*strPtr\i, -1, #PB_Ascii))
  TypeArray = #ArrayPB
 EndIf
  
 MessageRequester("Array from VB", "Number of elements = " + Str(NumElements))
 IdMemory = AllocateMemory(NumElements * 4)
 OffSet = 0
 
 For i = 1 To numElements
  
  *strPtr + SizeOf(INTEGER)
  
  If TypeArray = #ArrayVB 
   Text$ = PeekS(*strPtr\i, -1, #PB_Unicode) + "|"
  Else
   Text$ = PeekS(*strPtr\i, -1, #PB_Ascii) + "|"
  EndIf
   
  PokeS(IdMemory + OffSet, Text$)
  OffSet + (Len(Text$) * 4)
 
 Next
 
 ProcedureReturn IdMemory
  
EndProcedure
Code of EXE

Code: Select all

If OpenLibrary(0, "Test.dll")

 Dim ArrayString.s(10)
 ArrayString(0) = Trim(Str(ArraySize(ArrayString())))
  
 For i = 1 To 10
  ArrayString(i) = "Sentence " + Str(i)
 Next
 
 IdMemory = CallFunction(0, "ListStrings", ArrayString(), 10)
 
 
 For i = 0 To 100
  
  Sentence$ + Chr(PeekB(IdMemory + i))
  
 Next
 
 Debug Sentence$
 
 CloseLibrary(0)

EndIf
ImageThe happiness is a road...
Not a destination
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by Kwai chang caine »

I have found my mistake :D
It's in the lengt of UNICODE and ASCII

This is the new code fixed.
What you thinking about it ???

Code of DLL

Code: Select all

If OpenLibrary(0, "Test.dll")

 Dim ArrayString.s(10)
 ArrayString(0) = Trim(Str(ArraySize(ArrayString())))
  
 For i = 1 To 10
  ArrayString(i) = "Sentence " + Str(i)
 Next
 
 IdMemory = CallFunction(0, "ListStrings", ArrayString(), 10)
  
 For i = 0 To 1000
  Sentence$ + Chr(PeekB(IdMemory + i))
 Next
 
 Debug Sentence$
 
 CloseLibrary(0)

EndIf
Code of EXE

Code: Select all

ProcedureDLL ListStrings(*strPtr.INTEGER, Number)
 
 #ArrayPB = 1
 #ArrayVB = 2
 
 NumElements = Val(PeekS(*strPtr\i, -1, #PB_Unicode))
 TypeArray = #ArrayVB
 
 If Not NumElements
  NumElements = Val(PeekS(*strPtr\i, -1, #PB_Ascii))
  IdMemory = AllocateMemory(NumElements)
  TypeArray = #ArrayPB
 Else
  IdMemory = AllocateMemory(NumElements * 2) 
 EndIf
  
 MessageRequester("Array from VB", "Number of elements = " + Str(NumElements))
 OffSet = 0
 
 For i = 1 To numElements
  
  *strPtr + SizeOf(INTEGER)
  
  If TypeArray = #ArrayVB 
   Text$ = PeekS(*strPtr\i, -1, #PB_Unicode) + "|"
   OffSet + (Len(Text$) * 2)
  Else
   Text$ = PeekS(*strPtr\i, -1, #PB_Ascii) + "|"
   OffSet + (Len(Text$))
  EndIf
   
  PokeS(IdMemory + TempOffSet, Text$)
  TempOffSet = OffSet
 
 Next
 
 ProcedureReturn IdMemory
  
EndProcedure
ImageThe happiness is a road...
Not a destination
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by Kwai chang caine »

Ouuaaahhh KCC product a max :shock:
Again a new code with managing of lengh of memory
A mind is always strongly needed !!!!! :D

Code of DLL

Code: Select all

ProcedureDLL ListStrings(*strPtr.INTEGER, Number)
 
 #ArrayPB = 1
 #ArrayVB = 2
  
 If Not NumElements
  NumElements = Val(PeekS(*strPtr\i, -1, #PB_Ascii))
  IdMemory = AllocateMemory(NumElements)
  TypeArray = #ArrayPB
 Else
  IdMemory = AllocateMemory(NumElements * 2) 
  TypeArray = #ArrayVB
 EndIf
  
 MessageRequester("Array from VB", "Number of elements = " + Str(NumElements))
 OffSet = 4 : TempOffSet = 4
  
 For i = 1 To NumElements
  
  *strPtr + SizeOf(INTEGER)
  
  If TypeArray = #ArrayVB 
   Text$ = PeekS(*strPtr\i, - 1, #PB_Unicode) + "|"
   OffSet + (Len(Text$) * 2)
  Else
   Text$ = PeekS(*strPtr\i, - 1, #PB_Ascii) + "|"
   OffSet + (Len(Text$))
  EndIf
  
  PokeS(IdMemory + TempOffSet, Text$)
  TempOffSet = OffSet
   
 Next
 
 PokeL(IdMemory, OffSet)
 ProcedureReturn IdMemory
  
EndProcedure
Code of EXE

Code: Select all

If OpenLibrary(0, "Test.dll")

 Dim ArrayString.s(10)
 ArrayString(0) = Trim(Str(ArraySize(ArrayString())))
  
 For i = 1 To 10
  ArrayString(i) = "Sentence " + Str(i)
 Next
 
 IdMemory = CallFunction(0, "ListStrings", ArrayString(), 10)
 SizeMemory = PeekL(IdMemory)
  
 For i = 0 To SizeMemory
  
  Char = PeekB(IdMemory + 4 + i)
    
  If Char = 124
   Sentence$ + Chr(13)
  Else
   Sentence$ + Chr(Char) 
  EndIf 
  
 Next
  
 MessageRequester("VB/PB to DLL Test", Sentence$)
 CloseLibrary(0)

EndIf
ImageThe happiness is a road...
Not a destination
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: New try step by step of KCC for modify Array VB with DLL :-)

Post by Kwai chang caine »

Well,..... i have works all the day on this code
That's works not so bad, but i have an error when i freeing the memory the second time :cry:

Someone can help me please, because i have all tried...and i have always this error
I have write the maximum of explain for do understand

Code: Select all

; Written by KCC with precious help of SROD and also CPLBATOR, IDLE, XOMBIE
; This is the schema of the code
; I want to modify several time an arraystring of exe VB or PB in a DLL and return to it

;        EXE works
; 1/ Create ArrayEXE 
; 2/ Send the arrayEXE to DLL by pointer 

;        DLL works
; 3/ CreateArrayDLL 
; 4/ Copy ArrayExe To ArrayDLL (Add separator of field) in my case the separator is "|" 
; 5/ Modify ArrayDLL (Add/Modify lines) 
; 6/ Copy ArrayDLL in Memory
; 7/ Return pointer memory from DLL

;        EXE works
; 8/ Take pointer of memoryblock from the DLL
; 9/ Read and split memoryblock, and fill the ArrayEXE with the fields


; This procedure convert the pointer of array from EXE VB/PB to an array in the DLL
Procedure PointerArray2ArrayString(*strPtr.INTEGER, Number, Array Array2Fill.s(1))
  
 #ArrayPB = 1
 #ArrayVB = 2

 ; Test if the array is UNICODE
 NumElements = Val(PeekS(*strPtr\i, -1, #PB_Unicode))
   
 If Not NumElements ; The array is ASCII
  NumElements = Val(PeekS(*strPtr\i, -1, #PB_Ascii))
  TypeArray = #ArrayPB
 Else ; The array is UNICODE
  TypeArray = #ArrayVB
 EndIf
 
 Dim Array2Fill(NumElements)
 Array2Fill(0) = Str(NumElements) + "|" ; Write the lengh of array in line zero
  
 For i = 1 To NumElements ; Start to 1 for not replace the lengh of array
  
  *strPtr + SizeOf(INTEGER)
  
  Select TypeArray 
   Case #ArrayVB 
    Array2Fill(i) = PeekS(*strPtr\i, - 1, #PB_Unicode) + "|"
   Case #ArrayPB
    Array2Fill(i) = PeekS(*strPtr\i, - 1, #PB_Ascii) + "|"
  EndSelect
     
 Next
 
 ReDim Array2Fill(i)
  
EndProcedure

; This procedure convert an array string to a block of memory
Procedure ArrayString2PointerMemory(Array Array2Send.s(1))
  
 SizeArray2Send = ArraySize(Array2Send())
 *IdMemory2 = AllocateMemory(SizeArray2Send)
 
 If *IdMemory2
  
  OffSet = 4 : TempOffSet = 4
   
  For i = 0 To SizeArray2Send
   PokeS(*IdMemory2 + Offset, Array2Send(i))
   OffSet + Len(Array2Send(i))
  Next
   
  PokeL(*IdMemory2, Offset)
  ProcedureReturn *IdMemory2
 
 Else
 
  ProcedureReturn #False
 
 EndIf
  
EndProcedure

; This is THE procedure for modify the array
; In this example i want replace the big word "Sentence" by little "Kcc" :-)
; And add two lines

ProcedureDLL ChangeNameAndAddLine(*strPtr.INTEGER, NameToChange.s, NameToReplace.s, SizeArray)

 Dim Array2Modify.s(SizeArray)
 PointerArray2ArrayString(*strPtr.INTEGER, SizeArray, Array2Modify())
 
 For i = 1 To 5
  Array2Modify(i) = ReplaceString(Array2Modify(i), NameToChange, NameToReplace)
 Next
 
 ReDim Array2Modify(SizeArray + 2)
 
 For i = SizeArray + 1 To ArraySize(Array2Modify())
  Array2Modify(i) = "KCC add the line number " + Str(i) + "|"
 Next
 
 ProcedureReturn ArrayString2PointerMemory(Array2Modify())
 
EndProcedure

; This is a procedure for restore the array
; In this example i want replace the word "Kcc" by "Sentence"
; And delete two lines of the end

ProcedureDLL RestoreNameAndDeleteLine(*strPtr.INTEGER, NameToChange.s, NameToReplace.s, SizeArray)

 Dim Array2Modify.s(SizeArray)
 PointerArray2ArrayString(*strPtr.INTEGER, SizeArray, Array2Modify())
 
 For i = 1 To 5
  Array2Modify(i) = ReplaceString(Array2Modify(i), NameToChange, NameToReplace)
 Next
 
 ReDim Array2Modify(SizeArray - 2)
 ProcedureReturn ArrayString2PointerMemory(Array2Modify())
 
EndProcedure

; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************

; This procedure convert the block memory to an array 
Procedure Memory2Array(*IdMemory, Array ArrayModified.s(1))
 
 Dim ArrayModified.s(1000)
 SizeMemory = PeekL(*IdMemory)
 Line = 0
  
 For i = 0 To SizeMemory
  
  Char = PeekB(*IdMemory + 4 + i)

  If Char = 124
    Line + 1
   Continue
  EndIf 
  
  If Char
   ArrayModified(Line) + Chr(Char)
  EndIf 
 
 Next
 
 ReDim ArrayModified(Line - 1)
  
EndProcedure
 
;                Create original array

Dim ArrayString.s(10)
ArrayString(0) = Trim(Str(ArraySize(ArrayString())))

For i = 1 To 10
 ArrayString(i) = "Sentence " + Str(i)
Next

;                  Modify the array four time

For o = 1 To 2
 
 *IdMemory = ChangeNameAndAddLine(ArrayString(), "Sentence", "Kcc", ArraySize(ArrayString()))
 Memory2Array(*IdMemory, ArrayString())
 
 For i = 0 To ArraySize(ArrayString())
  Debug ArrayString(i)
 Next
 
 FreeMemory(*IdMemory)
 
 *IdMemory = RestoreNameAndDeleteLine(ArrayString(), "Kcc", "Sentence", ArraySize(ArrayString()))
 Memory2Array(*IdMemory, ArrayString())
 
 For i = 0 To ArraySize(ArrayString())
  Debug ArrayString(i)
 Next
 
 FreeMemory(*IdMemory)
 
Next

ImageThe happiness is a road...
Not a destination
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Modify Array VB and PB with a DLL, please need help :-(

Post by Kwai chang caine »

This a new code "more simple" :oops:
I have fix several bugs.....but always this problem of freeing memory the second time :cry:

Code: Select all

; This procedure convert the pointer of array from EXE VB/PB to an array in the DLL
Procedure PointerArray2ArrayString(*strPtr.INTEGER, Array Array2Fill.s(1), ArraySize)
   
 Dim Array2Fill(ArraySize)
 Array2Fill(0) = Str(ArraySize) + "|" ; Write the lengh of array in line zero
  
 For i = 1 To ArraySize ; Start to 1 for not replace the lengh of array
  
  *strPtr + SizeOf(INTEGER)
  Donnee$ = PeekS(*strPtr\i, - 1, #PB_Unicode) + "|"
  
  If Trim(Donnee$) <> ""
   Array2Fill(i) = PeekS(*strPtr\i, - 1, #PB_Ascii) + "|"
  Else 
   Array2Fill(i) = Donnee$
  EndIf
     
 Next
   
EndProcedure

; This procedure convert an array string to a block of memory
Procedure ArrayString2PointerMemory(Array Array2Send.s(1))
 
 OffSet = 4 
 SizeArray2Send = ArraySize(Array2Send())
 Array2Send(0) = Trim(Str(SizeArray2Send))
 *IdMemory2 = AllocateMemory(SizeArray2Send)
 PokeS(*IdMemory2 + Offset, Array2Send(0) + "|")
 OffSet + Len(Array2Send(0) + "|")
 
 If *IdMemory2
  
  For i = 1 To SizeArray2Send
   PokeS(*IdMemory2 + Offset, Array2Send(i))
   OffSet + Len(Array2Send(i))
  Next
   
  PokeL(*IdMemory2, Offset)
  ProcedureReturn *IdMemory2
 
 Else
 
  ProcedureReturn #False
 
 EndIf
  
EndProcedure

; This is THE procedure for modify the array
; In this example i want replace the big word "Sentence" by little "Kcc" :-)
; And add two lines

ProcedureDLL ChangeNameAndAddLine(*strPtr.INTEGER, NameToChange.s, NameToReplace.s, ArraySize)

 Dim Array2Modify.s(0)
 PointerArray2ArrayString(*strPtr.INTEGER, Array2Modify(), ArraySize)
 
 For i = 1 To 5
  Array2Modify(i) = ReplaceString(Array2Modify(i), NameToChange, NameToReplace)
 Next
 
 OldSizeArray2Modify = ArraySize(Array2Modify())
 ReDim Array2Modify(ArraySize(Array2Modify()) + 2)
  
 For i = OldSizeArray2Modify + 1 To ArraySize(Array2Modify())
  Array2Modify(i) = "KCC add the line number " + Str(i) + "|"
 Next
 
 ProcedureReturn ArrayString2PointerMemory(Array2Modify())
 
EndProcedure

; This is a procedure for restore the array
; In this example i want replace the word "Kcc" by "Sentence"
; And delete two lines of the end

ProcedureDLL RestoreNameAndDeleteLine(*strPtr.INTEGER, NameToChange.s, NameToReplace.s, ArraySize)

 Dim Array2Modify.s(0)
 PointerArray2ArrayString(*strPtr.INTEGER, Array2Modify(), ArraySize)
 
 For i = 1 To 5
  Array2Modify(i) = ReplaceString(Array2Modify(i), NameToChange, NameToReplace)
 Next
 
 ReDim Array2Modify(ArraySize(Array2Modify()) - 2)
 ProcedureReturn ArrayString2PointerMemory(Array2Modify())
 
EndProcedure

; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************
;                                           SEPARATION EXE / DLL
; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************

; This procedure convert the block memory to an array 
Procedure Memory2Array(*IdMemory, Array ArrayModified.s(1))
 
 SizeMemory = PeekL(*IdMemory)
 SizeArray = Val(PeekS(*IdMemory + 4))
 Dim ArrayModified.s(SizeArray)
 Line = 0
  
 For i = 0 To SizeMemory
  
  Char = PeekB(*IdMemory + 4 + i)

  If Char = 124
    Line + 1
   Continue
  EndIf 
  
  If Line > SizeArray
   Break
  EndIf 
   
  ArrayModified(Line) + Chr(Char)
    
 Next
 
 FreeMemory(*IdMemory)
 
EndProcedure
 
;                Create original array

Dim ArrayString.s(10)

For i = 1 To 10
 ArrayString(i) = "Sentence " + Str(i)
Next

;                  Modify the array four time

For o = 1 To 2
 
 *IdMemory = ChangeNameAndAddLine(ArrayString(), "Sentence", "Kcc", ArraySize(ArrayString()))
 Memory2Array(*IdMemory, ArrayString())
 
 For i = 0 To ArraySize(ArrayString())
  Debug ArrayString(i)
 Next
  
 *IdMemory = RestoreNameAndDeleteLine(ArrayString(), "Kcc", "Sentence", ArraySize(ArrayString()))
 Memory2Array(*IdMemory, ArrayString())
 
 For i = 0 To ArraySize(ArrayString())
  Debug ArrayString(i)
 Next
  
Next

ImageThe happiness is a road...
Not a destination
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Modify Array VB & PB with a DLL, please need help please :-(

Post by Kwai chang caine »

CLS have found my error on the french forum 8)
It's a bad allocatememory :oops:
This is the good code, if someone is interesting by miracle :lol:

Code: Select all

; Written by KCC with precious help of SROD and also CPLBATOR, CLS, IDLE, DENIS, XOMBIE, GEBONET
; This is the schema of the code
; I want to modify several time an arraystring of exe VB or PB in a DLL and return to it

;        EXE works
; 1/ Create ArrayEXE 
; 2/ Send the arrayEXE to DLL by pointer 

;        DLL works
; 3/ CreateArrayDLL 
; 4/ Copy ArrayExe To ArrayDLL (Add separator of field) in my case the separator is "|" 
; 5/ Modify ArrayDLL (Add/Modify lines) 
; 6/ Copy ArrayDLL in Memory
; 7/ Return pointer memory from DLL

;        EXE works
; 8/ Take pointer of memoryblock from the DLL
; 9/ Read and split memoryblock, and fill the ArrayEXE with the fields

; This procedure convert the pointer of array from EXE VB/PB to an array in the DLL
Procedure PointerArray2ArrayString(*strPtr.INTEGER, Array Array2Fill.s(1), ArraySize)
 
 #ArrayPB = 1
 #ArrayVB = 2
  
 Dim Array2Fill(ArraySize)
 Array2Fill(0) = Str(ArraySize) + "|" ; Write the lengh of array in line zero
  
 For i = 1 To ArraySize ; Start to 1 for not replace the lengh of array
   
  *strPtr + SizeOf(INTEGER)  
  
  If Not TypeArray
   
   Donnee$ = PeekS(*strPtr\i, - 1, #PB_Unicode) + "|" ; Array from VB
   
   If Left(Donnee$, 1) = "?"
    TypeArray = #ArrayPB
   Else 
    TypeArray = #ArrayVB
   EndIf
    
  EndIf 
  
  Select TypeArray
   Case #ArrayPB 
    Array2Fill(i) = PeekS(*strPtr\i, - 1, #PB_Ascii) + "|" ; Array from PB
   Case #ArrayVB
    Array2Fill(i) = PeekS(*strPtr\i, - 1, #PB_Unicode) + "|" ; Array from VB
  EndSelect
  
 Next
   
EndProcedure

; This procedure convert an array string to a block of memory
Procedure ArrayString2PointerMemory(Array Array2Send.s(1))
 
 OffSet = 4 
 SizeArray2Send = ArraySize(Array2Send())
 Array2Send(0) = Trim(Str(SizeArray2Send))
 MemorySize2Send = 0

 For i = 0 To SizeArray2Send
   MemorySize2Send + Len(Array2Send(i) + "|") 
 Next

 *IdMemory2 = AllocateMemory(MemorySize2Send + 4)
 PokeS(*IdMemory2 + Offset, Array2Send(0) + "|")
 OffSet + Len(Array2Send(0) + "|")
 
 If *IdMemory2
  
  For i = 1 To SizeArray2Send
   PokeS(*IdMemory2 + Offset, Array2Send(i))
   OffSet + Len(Array2Send(i))
  Next
   
  PokeL(*IdMemory2, Offset)
  ProcedureReturn *IdMemory2
 
 Else
 
  ProcedureReturn #False
 
 EndIf
  
EndProcedure

; This is THE procedure for modify the array
; In this example i want replace the big word "Sentence" by little "Kcc" :-)
; And add two lines

ProcedureDLL ChangeNameAndAddLine(*strPtr.INTEGER, NameToChange.s, NameToReplace.s, ArraySize)

 Dim Array2Modify.s(0)
 PointerArray2ArrayString(*strPtr.INTEGER, Array2Modify(), ArraySize)
 
 For i = 1 To 5
  Array2Modify(i) = ReplaceString(Array2Modify(i), NameToChange, NameToReplace)
 Next
 
 OldSizeArray2Modify = ArraySize(Array2Modify())
 ReDim Array2Modify(ArraySize(Array2Modify()) + 2)
  
 For i = OldSizeArray2Modify + 1 To ArraySize(Array2Modify())
  Array2Modify(i) = "KCC add the line number " + Str(i) + "|"
 Next
 
 ProcedureReturn ArrayString2PointerMemory(Array2Modify())
 
EndProcedure

; This is a procedure for restore the array
; In this example i want replace the word "Kcc" by "Sentence"
; And delete two lines of the end

ProcedureDLL RestoreNameAndDeleteLine(*strPtr.INTEGER, NameToChange.s, NameToReplace.s, ArraySize)

 Dim Array2Modify.s(0)
 PointerArray2ArrayString(*strPtr.INTEGER, Array2Modify(), ArraySize)
 
 For i = 1 To 5
  Array2Modify(i) = ReplaceString(Array2Modify(i), NameToChange, NameToReplace)
 Next
 
 ReDim Array2Modify(ArraySize(Array2Modify()) - 2)
 ProcedureReturn ArrayString2PointerMemory(Array2Modify())
 
EndProcedure

; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************
;                                           SEPARATION EXE / DLL
; ******************************************************************************************************************
; ******************************************************************************************************************
; ******************************************************************************************************************

; This procedure convert the block memory to an array 
Procedure Memory2Array(*IdMemory, Array ArrayModified.s(1))
 
 SizeMemory = PeekL(*IdMemory)
 SizeArray = Val(PeekS(*IdMemory + 4))
 Dim ArrayModified.s(SizeArray)
 Line = 0
  
 For i = 0 To SizeMemory
  
  Char = PeekB(*IdMemory + 4 + i)

  If Char = 124
   
   Line + 1
  
   If Line > SizeArray
    Break
   Else
    Continue 
   EndIf 
       
  EndIf 
     
  ArrayModified(Line) + Chr(Char)
    
 Next
 
 FreeMemory(*IdMemory)
 
EndProcedure
 
;                Create original array

Dim ArrayString.s(10)

For i = 1 To 10
 ArrayString(i) = "Sentence " + Str(i)
Next

;                  Modify the array four time

For o = 1 To 2
 
 *IdMemory = ChangeNameAndAddLine(ArrayString(), "Sentence", "Kcc", ArraySize(ArrayString()))
 Memory2Array(*IdMemory, ArrayString())
 
 For i = 0 To ArraySize(ArrayString())
  Debug ArrayString(i)
 Next
  
 *IdMemory = RestoreNameAndDeleteLine(ArrayString(), "Kcc", "Sentence", ArraySize(ArrayString()))
 Memory2Array(*IdMemory, ArrayString())
 
 For i = 0 To ArraySize(ArrayString())
  Debug ArrayString(i)
 Next
  
Next

ImageThe happiness is a road...
Not a destination
Post Reply