Few DLL questions

Just starting out? Need help? Post your questions and find answers here.
Nubcake
Enthusiast
Enthusiast
Posts: 195
Joined: Thu Feb 03, 2011 7:44 pm

Few DLL questions

Post by Nubcake »

According to the manual:
The DLL code is like a PureBasic code except than no real code should be written outside of procedure.
Don't write program code outside procedures. The only exception is the declaration of variables or structures.
What about DataSections? Does that count as code? I have an image that I included in my DataSection as a series of quads. Is it ok if I leave it outside a procedure?
Why should code be written in procedures? It doesn't really say why I'm just curious.
The declaration of arrays, linked-lists or map with Dim, NewList or NewMap must always be done inside the procedure AttachProcess.
I have arrays and lists in a few procedures here and there. How do I use the AttachProcess procedure for this?

Thanks
User avatar
Demivec
Addict
Addict
Posts: 4090
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Few DLL questions

Post by Demivec »

Nubcake wrote:According to the manual:

What about DataSections? Does that count as code? I have an image that I included in my DataSection as a series of quads. Is it ok if I leave it outside a procedure?
IMHO, the content of all DataSections are consolidated and stored together in a separate part of memory than procedures and other executable code. That would mean it doesn't matter where in the source code they are located, either inside a procedure declaration or otherwise.
Nubcake
Enthusiast
Enthusiast
Posts: 195
Joined: Thu Feb 03, 2011 7:44 pm

Re: Few DLL questions

Post by Nubcake »

Demivec wrote:
Nubcake wrote:According to the manual:

What about DataSections? Does that count as code? I have an image that I included in my DataSection as a series of quads. Is it ok if I leave it outside a procedure?
IMHO, the content of all DataSections are consolidated and stored together in a separate part of memory than procedures and other executable code. That would mean it doesn't matter where in the source code they are located, either inside a procedure declaration or otherwise.
Ok that's good to know because I wouldn't have known where to put it :)

What about Arrays and lists? I've been searching the forum and saw that array and list declarations are made global inside AttachProcess() but I have a Procedure that's not going to called directly but indirectly i.e the main proceduredll calls the procedures it needs. Should I put my array declarations and list declarations in AttachProcess() ? In DetachProcess() should the free'ing be done there?
User avatar
skywalk
Addict
Addict
Posts: 3996
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Few DLL questions

Post by skywalk »

Here's a DLL skeleton I use...

Code: Select all

; PB DLL NOTES:
;   All arrays, linked-lists or maps with Dim, NewList or NewMap must be done in Procedure AttachProcess()!
;   No program code outside Procedures, except declaration of variables or structures.
;   DirectX initialization routines cannot be written in Procedure AttachProcess().
;   Only Global strings can be returned from the DLL.
;   Not sure where DataSections are handled, but no crashes so far.
; COMPILE TO DLL:
;   #DLL_TEST    = 0
; COMPILER OPTIONS:
;   [x] Use Compiler:   PureBasic 5.11 (x86)
;   [ ] Use Icon:       
;   [ ] Enable inline ASM support
;   [ ] Create unicode executable
;   [ ] Create threadsafe executable
;   [ ] Enable OnError lines support
;   [ ] Enable XP skin support
;   [ ] Request Administrator mode for Windows Vista
;   [ ] Request User mode for Windows Vista (no virtualization)
;   Library Subsystem:
;   Executable Format:  Shared DLL
;   CPU:                All
;   File Format:        UTF-8
;   Version Info: auto set fields --> %yy.%mm.%dd
#DLL_TEST = 0   ; Compile as DLL
;#DLL_TEST = 1   ; Compile as EXE to test internal funcions.
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  CompilerIf #DLL_TEST
    ProcedureDLL AttachProcessME()
      ; Called when external program 1st loads dll
      ; Dim arrays, NewList Or NewMap done here(no DirectX init)
      ;Global.s out$ = Space(32)
      ;Global.i *s = AllocateMemory(255)
      Global.i bstr
      Debug "Dim'ng arrays..."
      ;MessageRequester(#PB_Compiler_Procedure,"Dim'ng arrays...",#MB_ICONINFORMATION)
      Global Dim SomeArray(0)
    EndProcedure

    ProcedureDLL DetachProcessME()
      ; Called when external program frees the dll
      ;If *s
      ;  FreeMemory(*s)
      ;EndIf
      SysFreeString_(bstr)
      Debug "Freeing arrays..."
      ;MessageRequester(#PB_Compiler_Procedure,"Freeing arrays...",#MB_ICONINFORMATION)
      FreeArray(SomeArray())
    EndProcedure
  CompilerElse
    ProcedureDLL AttachProcess(Instance)
      ; Called when external program 1st loads dll
      ; Dim arrays, NewList Or NewMap done here(no DirectX init)
      ;Global.s out$ = Space(32)
      ;Global.i *s = AllocateMemory(255)
      ;Global.i bstr
      Global Dim SomeArray(0)
    EndProcedure

    ProcedureDLL DetachProcess(Instance)
      ; Called when external program frees the dll
      ;If *s
      ;  FreeMemory(*s)
      ;EndIf
      ;SysFreeString_(bstr)
      FreeArray(SomeArray())
    EndProcedure

    ProcedureDLL AttachThread(Instance)
      ; Called when external thread attaches to dll
    EndProcedure

    ProcedureDLL DetachThread(Instance)
      ; Called when external thread releases dll
    EndProcedure
  CompilerEndIf
CompilerEndIf
;-{ TEST
CompilerIf #DLL_TEST
  AttachProcessME()
  ; ...Test stuff here...
  DetachProcessME() ; Last command
CompilerEndIf
;-} TEST
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Nubcake
Enthusiast
Enthusiast
Posts: 195
Joined: Thu Feb 03, 2011 7:44 pm

Re: Few DLL questions

Post by Nubcake »

Hi thanks for your example -> I have a few questions about it:

If you have a procedure that's not going to be used directly (It's not ProcedureDLL) should it be named as ProcedureDLL?
What is #TESTDLL? Is that a reserved constant or something you just use for justifying whether you compile as DLL or exe.
When freeing memory or allocated resources does it matter if I put it DetachProcess? Because my main function is going to be called a lot and it does a lot of allocating memory and freeing in the same procedure.
Is there anything I should know about Attach/DetachThead() like if someone uses the dll from another thread other than main something happens? (Does that make sense - I'm new to building DLLs)


Edit: I made my DLL but when I call a function using a prototype it works only once but the second time I get an IMA error? Is there an error amongst my code ?
PB.5.10 Win 7 x86

Edit: I think it's because I was freeing my array and lists (forgot about them)

Thanks again
Nubcake
Last edited by Nubcake on Mon Jul 22, 2013 12:17 am, edited 1 time in total.
User avatar
skywalk
Addict
Addict
Posts: 3996
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Few DLL questions

Post by skywalk »

Nubcake wrote:If you have a procedure that's not going to be used directly (It's not ProcedureDLL) should it be named as ProcedureDLL?
No, ProcedureDLL is only required if you plan to call it externally. Use Procedure for the rest. As for naming, choose a method you like for the 2 types.
ProcedureDLL mydll_Proc1()
Procedure __intProc1() ; <-- Leading '__' s mean internal only.
Nubcake wrote:What is #TESTDLL? Is that a reserved constant or something you just use for justifying whether you compile as DLL or exe.
This is just a made up constant since I sometimes have to test new DLL functions. I enable #DLL_TEST and change the compiler target from DLL to EXE and then step through a particular action.
Nubcake wrote:When freeing memory or allocated resources does it matter if I put it DetachProcess? Because my main function is going to be called a lot and it does a lot of allocating memory and freeing in the same procedure.
I show the FreeArray() in DetachProcess() since these were Globally defined. If your memory allocations are freed in other procedures, then you cannot free them again! :wink:
Nubcake wrote:Is there anything I should know about Attach/DetachThead() like if someone uses the dll from another thread other than main something happens?
Ha! Threads are a bit deeper to debug and discuss. But, you see there is an Instance parameter for you to manage. So, any Global DLL variables have to be "Instance aware". I tend to design away more than 1 threaded call to a single dll. Where is Trond? He was the thread guru.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Few DLL questions

Post by Josh »

Thorium wrote here
Thorium wrote:Globale Variablen brauchst nicht in AttachProcess packen. Die können auch bei DLL's ausserhalb der Prozeduren stehen.
My translation:
Thorium wrote:It's not necessary to write your global variables in the AttachProcess. They can be defined outside of procedures although in DLL's
sorry for my bad english
Nubcake
Enthusiast
Enthusiast
Posts: 195
Joined: Thu Feb 03, 2011 7:44 pm

Re: Few DLL questions

Post by Nubcake »

So I created a simple DLL that just returns a string but when I try to call in from another language i.e vb.net nothing happens.

Code: Select all

Global str.s = "Hello World"

ProcedureDLL.s func()
  ProcedureReturn str.s 
EndProcedure

Code: Select all

Public Declare Function dllfunc Lib "stringdll.dll" () As String
Why does it not work?
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Few DLL questions

Post by ts-soft »

Nubcake wrote:Why does it not work?
PB use nullterminated string, like C, unlike VB.
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
Nubcake
Enthusiast
Enthusiast
Posts: 195
Joined: Thu Feb 03, 2011 7:44 pm

Re: Few DLL questions

Post by Nubcake »

What changes do I need to make for it to work in PB or vb?
Thanks
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Few DLL questions

Post by ts-soft »

Code: Select all

Procedure StringToBStr(string.s)
  Protected *Buffer = AllocateMemory(StringByteLength(string, #PB_Unicode) + 2)
  Protected bstr_string.i
  If *Buffer
    PokeS(*Buffer, string, -1, #PB_Unicode)
    bstr_string = SysAllocString_(*Buffer)
    FreeMemory(*Buffer)
  EndIf
  ProcedureReturn bstr_string
EndProcedure



Global str.s = "Hello World"

ProcedureDLL func()
  ProcedureReturn StringToBStr(str)
EndProcedure
Not tested! I don't use VB.

Greetings - Thomas
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
skywalk
Addict
Addict
Posts: 3996
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Few DLL questions

Post by skywalk »

I don't use VB.NET but I have transferred string information between VB6 and PB with identical structures defined in both applications. I avoid BStr manipulations. It also depends if your PB app is compiled as Ascii or Unicode.
; PB
Structure X
n.i
s$
EndStructure
' VB6
Public Type X
n as long
s as string
End Type
Public myX as X
' Now pass myX ByRef to PB DLL.
Public Declare Function myPBDLL_DoSomething Lib "c:\myPBDLL.dll" (ByRef myX As X) As Long
' Also remember that the above Declare statement is case sensitive!
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Nubcake
Enthusiast
Enthusiast
Posts: 195
Joined: Thu Feb 03, 2011 7:44 pm

Re: Few DLL questions

Post by Nubcake »

ts-soft wrote:

Code: Select all

Procedure StringToBStr(string.s)
  Protected *Buffer = AllocateMemory(StringByteLength(string, #PB_Unicode) + 2)
  Protected bstr_string.i
  If *Buffer
    PokeS(*Buffer, string, -1, #PB_Unicode)
    bstr_string = SysAllocString_(*Buffer)
    FreeMemory(*Buffer)
  EndIf
  ProcedureReturn bstr_string
EndProcedure



Global str.s = "Hello World"

ProcedureDLL func()
  ProcedureReturn StringToBStr(str)
EndProcedure
Not tested! I don't use VB.

Greetings - Thomas
Tried but it only returned the first character of the string -> Poked around the forum and found that this works:

Code: Select all

SysAllocStringByteLen_(str,len(str))
Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: Few DLL questions

Post by Rinzwind »

"- The declaration of arrays, lists or map with Dim, NewList or NewMap must always be done inside the procedure AttachProcess."

Does this mean that any map or list in *any* included file/library can only be used within the DLL when declared in the AttachProcess procedure (messy to declare a Global in a procedure too, very messy when they come from everywhere)? That's not really workable is it? What about Threaded (can't even be used in a procedure itself)?

Never saw anything bad happen when just using Global NewMap at the top?

If not a problem, as Josh wrote long time ago above, then the doc is plain wrong (and super confusing as a result).
Post Reply