newLISP Fan Club

Forum => newLISP and the O.S. => Topic started by: neuwirthe on September 16, 2004, 12:24:10 AM

Title: DLL does not work from VBA
Post by: neuwirthe on September 16, 2004, 12:24:10 AM
I tried do use the DLL in Excel through VBA.

It does not work, it crashes.

I have used similar code for other DLLs, so I assume the

signature of newlispEvalStr is not right.

Loading works, I get a handle on the DLL

(there is code to check that!)



Public Declare Function EvalNewLISP Lib "newlisp" Alias "newlispEvalStr" (ByVal LExpr As String) As String

Private Declare Function LoadLibraryA Lib "kernel32" (ByVal s As String) As Long

Private Declare Sub FreeLibrary Lib "kernel32" (ByVal h As Long)

Dim NewLISPhandle As Long



Sub LoadNewLISP()

    On Error Resume Next

    Dim mylib As String

    mylib = ThisWorkbook.Path & "newlisp.dll"

    NewLISPhandle = LoadLibraryA(mylib)

    MsgBox NewLISPhandle

End Sub



Sub UnloadNewLISP()

    On Error Resume Next

    FreeLibrary (NewLISPhandle)

End Sub





Sub test()

    LoadNewLISP

    MsgBox EvalNewLISP("(+ 2 3)")

    UnloadNewLISP

End Sub
Title:
Post by: HPW on September 16, 2004, 03:27:09 AM
Have you seen this thread:



http://www.alh.net/newlisp/phpbb/viewtopic.php?t=353



By the way, what calling convention is used from VBA by default?

I see no definition in your code.



It must be stdcall



Tell us if you get it to work.

Maybe you can upload a XLS with demo-code?
Title: Further information, no solution yet
Post by: neuwirthe on September 16, 2004, 04:02:31 AM
This is getting really messy.

The problem is that VB and VBA cannot handle char * as return values,

strings work differently in VB.

I am investigating if it can be done.

I read the mentioned thread.

VB and VBA use stdcall, that is not the issue.

I added a test function returning integers

declared with DLLCALL to win32dll.c and it worked.



In VBA, one cannot declare the calling convention.



I already posted on microsoft.public.vb.general.discussion

to see if somebody knows how to write a C function

returning VB-usable strings.
Title:
Post by: HPW on September 16, 2004, 04:05:08 AM
I just rerun my old VB.NET test-code.



I get a strange error message using the latest GCC-compiled DLL.

After the third call I get an error "SystemNullReferenceException: ...."

When I change back to the BCC-DLL it runs stable!



I had no problems with the GCC-DLL in neobook and I have no reports from the neobook community about problems.



Strange effekt with GCC!
Title:
Post by: neuwirthe on September 16, 2004, 04:14:35 AM
I do not have BCC, and i had the same problem when I tried your

VB.NET example.
Title:
Post by: HPW on September 16, 2004, 04:26:45 AM
To get the BCC-compile it is no problem since Lutz contains the makefile for all flavors in the source distribution.



So when you want to get a BCC-DLL I or Lutz can compile it and upload somewhere.
Title:
Post by: Lutz on September 16, 2004, 05:02:02 AM
I have put a BCC compiled DLL in http://newlisp.org/downloads/development/BCC-dll/



I wonder if there are any other reports of the new MinGW DLL on other applications than VBA?



Lutz
Title:
Post by: neuwirthe on September 16, 2004, 06:21:32 AM
http://support.microsoft.com/default.aspx?scid=kb;en-us;187912

has a description of how to pass strings between VB6 (also applies to VBA) and a C dll.

I think this mandates a 2 step process.

Evaluate in the DLL and assign to a temporary buffer.

Let VB call a function giving the size of the string in VB.

Allocates string in VB. Call C DLL to fil VB buffer.

I volunteer for the VBA testing. Can somebody try to implement

this mechanism in the C DLL?

I am not good enough in C to do it.

I think it would be VERY important to be able to call NewLISP

in office apps, especially in Excel.
Title: Problem solved
Post by: neuwirthe on September 16, 2004, 08:13:56 AM
Thats the way it works in VBA:



Create a module in Excel's VBA editor.

Paste the code below.

Put the cursor inside the sub test

Press F5



Now we have NewLISP in Excel!!!!!!!!!!!!!!!!!!!!!!!!!!!!

More code to follow





Public Declare Function dllEvalNewLISP Lib "newlisp" Alias "newlispEvalStr" ( _

    ByVal LExpr As String) As Long

Private Declare Function lstrLen Lib "kernel32" Alias "lstrlenA" ( _

    lpString As Any) As Long

Private Declare Function lstrCpy Lib "kernel32" Alias "lstrcpyA" ( _

    lpString1 As Any, lpString2 As Any) As Long

Private Declare Function LoadLibraryA Lib "kernel32" (ByVal s As String) As Long

Private Declare Sub FreeLibrary Lib "kernel32" (ByVal h As Long)

Dim NewLISPhandle As Long



Sub LoadNewLISP()

    On Error Resume Next

    Dim mylib As String

    mylib = ThisWorkbook.Path & "newlisp.dll"

    NewLISPhandle = LoadLibraryA(mylib)

    Debug.Print NewLISPhandle

End Sub



Sub UnloadNewLISP()

    On Error Resume Next

    FreeLibrary (NewLISPhandle)

End Sub





Function EvalNewLISP(LispExpression As String) As String

    Dim resHandle As Long

    Dim result As String

    resHandle = dllEvalNewLISP(LispExpression)

    result = Space$(lstrLen(ByVal resHandle))

    lstrCpy ByVal result, ByVal resHandle

    EvalNewLISP = result

End Function



Sub test()

    LoadNewLISP

    MsgBox EvalNewLISP("(* 56 56)")

    UnloadNewLISP

End Sub
Title:
Post by: HPW on September 16, 2004, 10:43:57 AM
>Now we have NewLISP in Excel!!!!!!!!!!!!!!!!!!!!!!!!!!!!



Great news! I tried your example and it works for me in Excel 2002.



>More code to follow



More sample code always welcome to attract more user to newLISP.

Spread the word of newLISP to the VBA/VB world.
Title:
Post by: HPW on September 16, 2004, 10:55:18 AM
And it seems to work with the current GCC-newLISP.dll

And it is found through the path enviroment,

since I had not copied it to the XLS-path.

And did you notice that it hold the symbol data between subsequent call's with F5. That the same nice thing as on other platform we tested. (neobook, powerbasic, purebasic)
Title:
Post by: Lutz on September 16, 2004, 04:41:47 PM
Thanks 'neuwirthe' for researching this! I tried to do use newlisp.dll in Excel again and again but did not succeed, just don't know enough about VBA. In a previous GUI version of newLISP you could do DDE with Excel.



On first sight I don't fully understand what you are doing, but I will dig into it and perhaps it is possible with some changes in newlisp.dll to make a newlisp.dll import into Excel more streight forward.



Thanks again ... the possibility of using Excel with newLISP is exciting. For me the spreadsheet is still the crown of all computer programs.



Lutz
Title:
Post by: HPW on September 16, 2004, 11:15:35 PM
I just take my Excel 2002 file and test in Excel97 with success.



>with some changes in newlisp.dll to make a newlisp.dll import into Excel more streight forward.



I think it is streight forward enough. He only uses WIN API functions to convert the result into the right format.
Title:
Post by: Lutz on September 17, 2004, 07:25:57 AM
It seems to me that at in least in VBA Excel you don't need the functions 'LoadNewLISP()' and 'UnloadNewLISP()'



I just did:

Public Declare Function dllEvalNewLISP Lib "c:newlispnewlisp.dll" Alias "newlispEvalStr" (ByVal LExpr As String) As Long
Private Declare Function lstrLen Lib "kernel32" Alias "lstrlenA" (lpString As Any) As Long
Private Declare Function lstrCpy Lib "kernel32" Alias "lstrcpyA" (lpString1 As Any, lpString2 As Any) As Long
Private Declare Function LoadLibraryA Lib "kernel32" (ByVal s As String) As Long
Private Declare Sub FreeLibrary Lib "kernel32" (ByVal h As Long)
Dim NewLISPhandle As Long

Function EvalNewLISP(LispExpression As String) As String
Dim resHandle As Long
Dim result As String
resHandle = dllEvalNewLISP(LispExpression)
result = Space$(lstrLen(ByVal resHandle))
lstrCpy ByVal result, ByVal resHandle
EvalNewLISP = result
End Function

Sub TestEvalNewLISP()
MsgBox EvalNewLISP("(* 256 256)")
End Sub


And then put



=EvalNewLISP("(+ 3 4)")



in an Excel cell and see "7"



May be 'LoadNewLISP()' and 'UnloadNewLISP()' are necessary in other VB applications? in Excel the Declare alone seems to be sufficient for newlisp.dll to be loaded.



Lutz



ps: for VBA newbees: Note that some of the Declaration lines wrap in this post, unify them again when pasting into the VB editor in Excel
Title:
Post by: HPW on September 17, 2004, 07:45:45 AM
Real nice, of cource we had to build a better example for newbees to point out the advantage of embeded newLISP.



Here they would say it is so simple in Excel: =3+4



;-)
Title:
Post by: neuwirthe on September 25, 2004, 11:37:19 AM
is there some repository where I can put examples? I now have VB6 and Excel examples as zip files.



About LoadNewLISP:

Your code works with a fixed path to newlisp. LoadNewLISP in the new examples will pompt you for its location when it is not found immediately.



I also think that as long as newlisp.dll is on the path, LoadNewLISP is not necessary. But I think it helps people if you show them how to handle a somehwat more difficult situation.
Title:
Post by: neuwirthe on September 25, 2004, 12:01:54 PM
Some more things:

Strings in VB are rather difficult, there is a special type BSTR which has to be used in C programs to be called by VB, but support for this type seems only to be supplied for Microsoft compilers. Therefore I am using a workaround calling WinAPI functions converting C's char * to VB strings.



Another thing: if you like Excel, try to have a look at my book



The Active Modeler - Mathematical Modeling with Microsoft Excel

Erich Neuwirth - University of Vienna (Austria)

Deane Arganbright - University of Tennessee, Martin

ISBN 0534420850
Title:
Post by: HPW on September 25, 2004, 12:05:06 PM
I think Lutz will be interested in the demo-code.

(Send it to 'lutz at nuevatec dot com' and put newlisp in the subject)

Until Lutz has put it on the server, you could also send it to my mail.

(hpwickern at hpwsoft dot de)

Thanks again for working it out.

This is one more sample for the practical use of newLISP for real world work.
Title:
Post by: Lutz on September 25, 2004, 12:10:09 PM
Hi Erich,



You can send the zip file to me: lutz at nuevatec dot com . put the word 'newlisp' in the subject line, so it will not be eaten by my spam filters. I can than link to it from the 'Code Contributions' section.



Or if you can host it yourself, I can link to it.



Lutz



ps: oops, looks like HPW's and my brain worked in sync on this
Title:
Post by: neuwirthe on September 25, 2004, 12:37:13 PM
I just tried to adapt the WinAPI technique to the VB.NET example, and it does not work at all. I do not know VB.NET. Perhaps you can try to convert the VB6 technique to VB.NET? Maybe this takes care of the crashes in VB.NET
Title:
Post by: HPW on September 25, 2004, 01:45:34 PM
I have a working VB.NET example posted here and as I posted, found to have problems with the GCC-compiled version of newLISP.dll

It was working with the BCC-compiled flavor. So interested should use this flavor until we found out what the problem could be.
Title:
Post by: neuwirthe on September 25, 2004, 02:58:27 PM
I was using your VB.NET example as a starter.

Have you done extensive testing with the BC compiled version?

I fear that it might have the same problems lik the GCC version

in a longer run.

Therefore, I think it would be worthwhile to adapt the lstrCpy method

to VB.NET also. but I have not found a way of doing this.
Title:
Post by: HPW on September 25, 2004, 11:27:08 PM
>Have you done extensive testing with the BC compiled version?



Not realy! Was only simple testing with calling one simple function again an again.

GCC crashed with the third call. BCC run a lot calls without problems, but I did not count. More testing have to be done if their is interest to run under .NET. My interest for the moment is to do testing for the WINCE-port as soon I get some hardware.
Title:
Post by: neuwirthe on September 26, 2004, 09:08:58 AM
Here is VB.NET code working with h GCC compiled version.



Public Class Form1

    Inherits System.Windows.Forms.Form





    <DllImport("c:newlispnewlisp.dll", _

               EntryPoint:="dllEvalStr", _

               CharSet:=CharSet.Ansi, _

               CallingConvention:=CallingConvention.StdCall)> _

    Public Shared Function dllNewlispeval(ByVal txt As String) As System.Text.StringBuilder

        ' Leave function empty - DLLImport attribute forwards calls to newlisp

    End Function



    Public Shared Function NewLisp(ByVal LispExpression As String) As String

        Dim ResultObject As System.Text.StringBuilder

        ResultObject = dllNewlispeval(LispExpression)

        Return ResultObject.ToString

    End Function





    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim RetVal As String ' Stores the return value.

        Try

            TextBox2.Text = NewLisp(TextBox1.Text)

        Catch ex As Exception           ' Catch the error.

            MsgBox(ex.ToString)         ' Show friendly error message.

        End Try

    End Sub



#Region " Windows Form Designer generated code "

#I do not include this code

#End Region



End Class
Title:
Post by: HPW on September 26, 2004, 11:33:29 AM
Erich,



Thanks again for this.

I will give it a try.
Title:
Post by: HPW on September 26, 2004, 12:18:49 PM
I have tested your code but I get errors.

Which versions of visual studio/VB.NET and framework are you using?



Also note that this is the old EntryPoint:="dllEvalStr".

The new is EntryPoint:="newlispEvalStr"
Title:
Post by: HPW on September 26, 2004, 11:13:35 PM
Erich,



I have got your sample code and only start 'NewLispDotNet.exe' from the bin-folder. I get the sample form and type '(setq a 5)' and hit 'Evaluate'. Then I hit it a second and a third time. First and second return 5. With the third hit I get:



System.NullReferenceException: Der Objektverweiss wurde nicht auf eine Objektinstanz festgelegt.

at NewLispDotNet.Form1.dllNewlispeval(String txt)

...

...



Then I compiled the latest 8.2.0 source to a BCC-DLL and replace the GCC-DLL with it. Then I could use your VB.NET sample without problem.
Title:
Post by: HPW on September 28, 2004, 05:37:24 AM
In current:



http://www.newlisp.org/code/NewLispDotNet.zip



in Module1.vb is the deprecated 'dllEvalStr' used instead of 'newlispEvalStr'.

Not yet a problem but maybe in the future.