Use several DLL instances

Machine-specific discussion
Unix, Linux, OS X, OS/2, Windows, ..?
Locked
ale870
Posts: 297
Joined: Mon Nov 26, 2007 8:01 pm
Location: Italy

Use several DLL instances

Post by ale870 »

Hi,

I wish to load several DLL instances of the same "newlisp.dll" in order to create several insulated environments. Even if I could use CONTEXT it is not the best way, since the script could change the context creating some seriuos errors.

I'm working in Pure Basic and I tried this:

Code: Select all

OpenLibrary(0, "newlisp.dll")
OpenLibrary(1, "newlisp.dll")

Debug "Set:" + PeekS(CallFunction(0, "newlispEvalStr", @"(setq a1 100)"))
Debug "Get 1:" + PeekS(CallFunction(0, "newlispEvalStr", @"a1"))

Debug "Get 2:" + PeekS(CallFunction(1, "newlispEvalStr", @"a1"))

CloseLibrary(1)
CloseLibrary(0)
As you can see I opened twice the same DLL, and I associated it to id 1 and 2.
But when I execute I obtain:

Code: Select all

Set:100
Get 1:100
Get 2:100

As you can see, the "GET 2:" return me the value "100" that I set in the first DLL call (id:1). It means windows, even if I opened the same dll in two different places, it uses the same working area.

Can you give me some hints/suggestions to avoid this problem?

Thank you!
--

ale870
Posts: 297
Joined: Mon Nov 26, 2007 8:01 pm
Location: Italy

Post by ale870 »

I made some tests and...
I tried a trick: make a copy of newlisp.dll (newlisp2.dll) but it seems the second copy does NOT work.
I friend of mine made the same test with another dll and it works...

So the "problem" seems related to newlisp.dll

Is there anything related to that library if loaded more than once?
--

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

Yes that is correct.. ircc.. ;-)

Internaly the Library is known to PB when you open it in the same segment..
If you rename it or what ever doesnt matter..

You can only use twice the same library if you fork inside PB the loading of
the library's and then communicate internaly between the two sessions...
(but i never tried this in PB)

The same would happen if you would open twice another i.e. Libc...

But why would you like to open twice the same library?
-- (define? (Cornflakes))

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

even if I opened the same dll in two different places, it uses the same working area.
This is only true if you open frome the same parent process.

If you have runnning two parent processes, then both will create separate workspaces for that DLL.

ale870
Posts: 297
Joined: Mon Nov 26, 2007 8:01 pm
Location: Italy

Post by ale870 »

Fork? So creating subprocess?
I will try to work in thread (even if a thread (win) is so much different from processes (unix).

I need to create two environments because I need to create a working environment, then I need to create a "test" environemnt (clean and independent from the first one).

I'm creating a game framework, and I want to create for the final users two environments for "production" and for "test", clean and separated (they do not need to communicate).
--

ale870
Posts: 297
Joined: Mon Nov 26, 2007 8:01 pm
Location: Italy

Post by ale870 »

Nothing.
Threads do not work.
And processes is not feasible under windows (no "fork" exists).
I will try another way (I will try to force CONTEXT usages in order to separate environments).

Thank you
--

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

what about creating the main program and during startup extract the sub-program from the main-program actualy youre unzipping/unpacking it from the parent and executing it.. You could use "RunProgram" on a
Purebasic Memory segment..(the place where your second program is stored)..
-- (define? (Cornflakes))

ale870
Posts: 297
Joined: Mon Nov 26, 2007 8:01 pm
Location: Italy

Post by ale870 »

It could be a (bad) solution. In fact in that case I would have create a full communication protocol, plus some other checks to verify if a process crash... huge work.
Using fork could be a great solution but Window does not support fork :-(
--

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

You don't need fork. You could start two newlisp processes. Not the DLL, but two running newLISPs listening on pipes executing commands.

A second possibility is, two run two newlisp servers:

newlisp -c -d 10000
newlisp -c -d 10001

they listen then on the ports just like on the newLISP command line. You then send via TCP/IP line-feed terminated newLISP expressions. And listen back for the result.

Try staring a newLISP server and then use telnet to talk to it to see how it would work for your Basic app.

This is exactly the way the Java based IDE communicates with newLISP. Think of the Java IDE beeing your Basic application.

May be the first alternative using pipes, will have a higher through-put.

ale870
Posts: 297
Joined: Mon Nov 26, 2007 8:01 pm
Location: Italy

Post by ale870 »

Interesting possibility! Even if I knew about its existence, I didn't think to that solution.
I will investigate both solutions, since for me performance are a key-feature (but I could make a working environment using a dll, then create a newlisp independent server for testing purposes only! This could be a very good solution!)

Thank you for your suggestion!
--

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

dont forget ..PB must do GUIevents and Networking in threads..
..else you wont be Async and that would be a shame for your project..

..I have that networking solution somewhere on the shelfs with PB and
newlisp doing 2D drawings in threads.. Ill see if i can find it..
-- (define? (Cornflakes))

ale870
Posts: 297
Joined: Mon Nov 26, 2007 8:01 pm
Location: Italy

Post by ale870 »

Thank you for your suggestions, but I already considerred it.
About 3D, I'm using PureGDK, and for GUI I will detect events either using callback (setCallback) and using non-bloking event checking.
That is mandatory for me, since I need, at the same time, render the 3D scene (done using a thread!).

Thank you!
--

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

here a pre alpha release from 2 years ago...it did build it to a full
version but can find the source..hehe...disk craches etc.. ;-)

Code: Select all

;------------------------------------------------------------------------------------------------
;; version 1.0 PB linux Beta 4
;; UDP wall, displays all info from UDP port 8080 on an Image-Wall
;; to create more output then forward all your udp ports to 8080 ;-)
;;------------------------------------------------------------------------------------------------

;;------------------------------------------------------------------------------------------------
;;globals
;;------------------------------------------------------------------------------------------------
Global port = 8080
Global T.s
Global C.s
Global true = 1
Global false = 0

;;------------------------------------------------------------------------------------------------
;; console init
;;------------------------------------------------------------------------------------------------
OpenConsole()


;;------------------------------------------------------------------------------------------------
;; check desktop
;;------------------------------------------------------------------------------------------------
If ExamineDesktops()
  Global dw = DesktopWidth(0)
  Global dh = DesktopHeight(0)
  Global dd = DesktopDepth(0)
  Global df = DesktopFrequency(0)
  Global dn.s = DesktopName(0)
EndIf

;;------------------------------------------------------------------------------------------------
;; create image of dw - 10 x400
;;------------------------------------------------------------------------------------------------


;;------------------------------------------------------------------------------------------------
;;check network
;;------------------------------------------------------------------------------------------------
PrintN("udpGUI: Running")
If InitNetwork() = 0 : PrintN("No network available!") : End : EndIf
If CreateNetworkServer(0,port,#PB_Network_UDP) = 0 : PrintN("Cant bind to "+Str(port)+" !") :  End : EndIf

;;------------------------------------------------------------------------------------------------
;;create update image
;;------------------------------------------------------------------------------------------------
Procedure _pixel(x.w, y.w)
    StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Transparent)
    BackColor(RGB(Random(255),Random(255),Random(255)))
    FrontColor(RGB(Random(255),Random(255),Random(255)))
    Plot(x,y)
    StopDrawing()
    SetGadgetState(0, ImageID(0))
EndProcedure

Procedure _square(x.w, y.w, w.w, h.w)
    StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Transparent)
    BackColor(RGB(Random(255),Random(255),Random(255)))
    FrontColor(RGB(Random(255),Random(255),Random(255)))
    Box(x,y,w,h)
    StopDrawing()
    SetGadgetState(0, ImageID(0))
EndProcedure

Procedure _circle(x.w, y.w, r.w)
    StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Transparent)
    BackColor(RGB(Random(255),Random(255),Random(255)))
    FrontColor(RGB(Random(255),Random(255),Random(255)))
    Circle(x,y,r)
    StopDrawing()
    SetGadgetState(0, ImageID(0))
EndProcedure

Procedure _text(x.w, y.w, t.s)
    StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Transparent)
    BackColor(RGB(Random(255),Random(255),Random(255)))
    FrontColor(RGB(Random(255),Random(255),Random(255)))
    DrawText(x,y,t)
    StopDrawing()
    SetGadgetState(0, ImageID(0))
EndProcedure
;;------------------------------------------------------------------------------------------------
;;network UDP thread
;;------------------------------------------------------------------------------------------------
Procedure listener()
Repeat
   Delay(1)
   server_event = NetworkServerEvent()
    If server_event
            client = EventClient()
            Select server_event

                        Case #PB_NetworkEvent_Data
                                *buffer = AllocateMemory(65)
                                    If ReceiveNetworkData(client, *buffer, 64)
                                        T = PeekS(*buffer)
                                        T = LTrim(T)
                                        T = RTrim(T)
                                        T = LCase(T)
                                    EndIf
                                 FreeMemory(*buffer)

                               C= IPString(GetClientIP(client)) + ":" + Str(GetClientPort(client))
                               CloseNetworkConnection(client)
            EndSelect
    EndIf
Until quit = 1
EndProcedure

udpT = CreateThread(@listener(), 1)
If udpT = 0 : PrintN("Error creating thread!") : End : EndIf


;;------------------------------------------------------------------------------------------------
;; main window
;;------------------------------------------------------------------------------------------------
If OpenWindow(0, 0, 0, 0, 0, "udpGUIl", #PB_Window_Invisible |#PB_Window_MinimizeGadget| #PB_Window_MaximizeGadget|#PB_Window_Maximize )
    CreateGadgetList(WindowID(0))

Repeat
        ;Delay(1)
         EventID = WaitWindowEvent(100)

              ;; init a new window  hide it create an image on it
              If StringField(T, 1, " ") = "init" And init = false
                                        ResizeWindow(0,Val(StringField(T, 2, " ")), Val(StringField(T, 3, " ")),Val(StringField(T, 4, " ")),Val(StringField(T, 5, " ")))
                                        HideWindow(0, 0)
                                        SetWindowTitle(0,StringField(T, 6, " "))
                                        ImageGadget(0, 0, 0, Val(StringField(T, 4, " ")),Val(StringField(T, 5, " ")) , ImageID(0))
                                        CreateImage(0, Val(StringField(T, 4, " ")),Val(StringField(T, 5, " ")) , #PB_Image_DisplayFormat )
                                        init = true;

             ElseIf  init = true
                                        ;; pixel x y
                                        If       StringField(T, 1, " ") = "pixel"
                                                _pixel(Val(StringField(T, 2, " ")), Val(StringField(T, 3, " ")))

                                        ;; box x y w h
                                        ElseIf StringField(T, 1, " ") = "square"
                                                _square(Val(StringField(T, 2, " ")), Val(StringField(T, 3, " ")),Val(StringField(T, 4, " ")),Val(StringField(T, 5, " ")))

                                        ;; circle x y r
                                        ElseIf StringField(T, 1, " ") = "circle"
                                                _circle(Val(StringField(T, 2, " ")), Val(StringField(T, 3, " ")),Val(StringField(T, 4, " ")))

                                       ;; text x y text
                                       ElseIf StringField(T, 1, " ") = "text"
                                                _text(Val(StringField(T, 2, " ")), Val(StringField(T, 3, " ")), LTrim(RemoveString(T,Left(T,FindString(T,StringField(T, 4, " "),1) - 1  ))))

                                      ;; hides the window
                                      ElseIf StringField(T, 1, " ") = "hide"
                                                 HideWindow(0, 1)

                                       ;; shows the window
                                       ElseIf StringField(T, 1, " ") = "show"
                                                 HideWindow(0, 0)

                                       ;; make window sticky on top of all
                                       ElseIf StringField(T, 1, " ") = "wett"
                                                 StickyWindow(0, 1)

                                       ;; make window dray, normal behavior
                                       ElseIf StringField(T, 1, " ") = "dry"
                                                 StickyWindow(0, 0)

                                       ElseIf StringField(T, 1, " ") = "clean"
                                                w = ImageWidth(0)
                                                h = ImageHeight(0)
                                                FreeImage(0)
                                                CreateImage(0, w, h , #PB_Image_DisplayFormat )

                                       ;; close all
                                       ElseIf StringField(T, 1, " ") = "close"
                                                quit = true

                                       EndIf
                EndIf

        T = ""
        Until EventID = #PB_Event_CloseWindow  Or quit = true
EndIf

KillThread(udpT)
CloseNetworkServer(0)
CloseConsole()
End


-- (define? (Cornflakes))

ale870
Posts: 297
Joined: Mon Nov 26, 2007 8:01 pm
Location: Italy

Post by ale870 »

Thank you!
I will study it!
--

ale870
Posts: 297
Joined: Mon Nov 26, 2007 8:01 pm
Location: Italy

Post by ale870 »

Lutz wrote:You don't need fork. You could start two newlisp processes. Not the DLL, but two running newLISPs listening on pipes executing commands.

A second possibility is, two run two newlisp servers:

newlisp -c -d 10000
newlisp -c -d 10001

they listen then on the ports just like on the newLISP command line. You then send via TCP/IP line-feed terminated newLISP expressions. And listen back for the result.

Try staring a newLISP server and then use telnet to talk to it to see how it would work for your Basic app.

This is exactly the way the Java based IDE communicates with newLISP. Think of the Java IDE beeing your Basic application.

May be the first alternative using pipes, will have a higher through-put.
After some tests using DLL, I decided to try pipe method.
Results are simply incredible! newLisp pipe is great!

I made two tests: first test using a single thread, and another test using 10 (ten!) threads running together, to solve the same problem.

I have a Dual quad core CPU (we can say they are "almost" 4 CPU), Windows Vista and 4Gb Ram.

It's incredible:

Single thread took about 25 seconds.
Multithread took about 11 seconds!!!

It means that using multiprocessors (newlisp -c) called ten times (10 newLisp interpreters running all together!), PB, newLisp and Windows Vista can use multicore in an effective way (not only words... but facts! Multi-CPU is really running!).

Furthermore consider that single thread my CPUs were busy at about 35%, but using ten threads they were busy always to 100% !!!

I definitively use this method to implement my game framework using newLisp ;-)

Thank you!
--

HPW
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Post by HPW »

One thing you have to consider when you want to distribute such a multi-process conzept,
is the fact that some security softwares pops up whith some warnings when the processes want to start TCP-intercommunications.
That might be irritating your users.
Hans-Peter

ale870
Posts: 297
Joined: Mon Nov 26, 2007 8:01 pm
Location: Italy

Post by ale870 »

Yes, you are right.
I don't know which parameters it checks, since my PC does not give that message.
I know that some messages are sent from firewalls not "native" O.S.
--

Locked