.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Unable to find an entry point in DLL 'acad.exe'

24 REPLIES 24
SOLVED
Reply
Message 1 of 25
Anonymous
8711 Views, 24 Replies

Unable to find an entry point in DLL 'acad.exe'

I'm trying to adapt the code used to answer this question here into my own code. I want to be able to run lisp using the commands and methods I've written:

 

public class MyCommands
{
// Type of resbuf element
const int RTNONE = 5000; /* No result */
const int RTREAL = 5001; /* Real number */
const int RTPOINT = 5002; /* 2D point X and Y only */
const int RTSHORT = 5003; /* Short integer */
const int RTANG = 5004; /* Angle */
const int RTSTR = 5005; /* String */
const int RTENAME = 5006; /* Entity name */
const int RTPICKS = 5007; /* Pick set */
const int RTORINT = 5008; /* Orientation */
const int RT3DPOINT = 5009; /* 3D point - X, Y, and Z */
const int RTLONG = 5010; /* Long integer */
const int RTVOID = 5014; /* Blank symbol */
const int RTLB = 5016; /* list begin */
const int RTLE = 5017; /* list end */
const int RTDOTE = 5018; /* dotted pair */
const int RTNIL = 5019; /* nil */
const int RTDXF0 = 5020; /* DXF code 0 for ads_buildlist only */
const int RTT = 5021; /* T atom */
const int RTRESBUF = 5023; /* resbuf */

[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("acad.exe", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedEvaluateLisp@@YAHPB_WAAPAUresbuf@@@Z")]
private static extern int acedEvaluateLisp(string lispLine, out IntPtr result);

public static ResultBuffer AcadEvalLisp(string arg)
{
IntPtr rb = IntPtr.Zero;
acedEvaluateLisp(arg, out rb);
if (rb != IntPtr.Zero)
{
try
{
ResultBuffer rbb = DisposableWrapper.Create(typeof(ResultBuffer), rb, true) as ResultBuffer;
return rbb;
}
catch
{
return null;
}
}
return null;
}
// Define Command "CSharpToLisp"
// Only for testing we can define this function.
//
// Example:
// Command: CSharpToLisp
// Enter lisp expression: (+ 100 50 30 20 10)
// -----------------------------
// 5003 -> 210
// -----------------------------
[CommandMethod("CSharpToLisp")]
public static void test()
{
PromptResult rs = AcadApp.DocumentManager.MdiActiveDocument.Editor.GetString("\nEnter lisp expression: ");
if (rs.Status == PromptStatus.OK && rs.StringResult != "")
{
ResultBuffer rb = AcadEvalLisp(rs.StringResult);
if (rb != null)
{
PrintResbuf(rb);
}
else
{
AcadApp.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nError in evaluation");
}
}
}
// This code was posted by Tony Tanzillo:
// http://discussion.autodesk.com/thread.jspa?messageID=5094658
private static void PrintResbuf(ResultBuffer rb)
{
string s = "\n-----------------------------";
foreach (TypedValue val in rb)
{
s += string.Format("\n{0} -> {1}", val.TypeCode,
val.Value.ToString());
s += "\n-----------------------------";
}
AcadApp.DocumentManager.MdiActiveDocument.Editor.WriteMessage(s);
}

 

I load my DLL and run  the command CSHARPTOLISP in AutoCAD. The test input I've been using is (+ 1 1) which outputs 2 as expected but then shows this error message

 

error.PNG

 

I'm assuming I need to adjust the entry point but am not sure how to go about doing that...

Tags (3)
24 REPLIES 24
Message 2 of 25
_gile
in reply to: Anonymous

Try this:

 

using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput; 
using Autodesk.AutoCAD.Runtime;

namespace InvokeLispSample
{
    public class CommandMethods
    {
        /* This TEST command calls the 'foo' LISP function which requires a list as argument
         * and returns the reversed list.
         * 
         * (defun foo (l) (reverse l)) (vl-acad-defun "foo")
         */
        [CommandMethod("Test", CommandFlags.Modal)]
        public void Test()
        {
            // build the arguments list
            ResultBuffer args = new ResultBuffer(
                new TypedValue((int)LispDataType.Text, "foo"),
                new TypedValue((int)LispDataType.ListBegin),
                new TypedValue((int)LispDataType.Text, "test"),
                new TypedValue((int)LispDataType.Int16, 42),
                new TypedValue((int)LispDataType.Double, 25.4),
                new TypedValue((int)LispDataType.ListEnd));

            // call the LISP fuction anf get the return value
            ResultBuffer result = Application.Invoke(args);

            // print the return value
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            ed.WriteMessage(result.ToString());
        }
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 25
autodaug
in reply to: _gile

It's a lot cleaner to use Application.Invoke(), but fwiw, about the entry point, as of AutoCAD 2013 it is exported from accore.dll instead of acad.exe.

 

Also, the function has two pointer args, which causes a difference in the name mangling between 32 and 64 bit binaries. Looks like you're using the 32-bit one.

 

32-bit: ?acedEvaluateLisp@@YAHPB_WAAPAUresbuf@@@Z
64-bit: ?acedEvaluateLisp@@YAHPEB_WAEAPEAUresbuf@@@Z

 

Message 4 of 25
Anonymous
in reply to: _gile

Thanks for your help _gile! I've implemented your code like this:

 

[CommandMethod("Test", CommandFlags.Modal)]
public void Test()
{

// build the arguments list
ResultBuffer args = new ResultBuffer(
new TypedValue((int)LispDataType.Text, "HELLO"),
//new TypedValue((int)LispDataType.ListBegin),
//new TypedValue((int)LispDataType.Text, "T-600"),
//new TypedValue((int)LispDataType.Text, "t")
//new TypedValue((int)LispDataType.ListEnd)
);

// call the LISP fuction anf get the return value
ResultBuffer result = Autodesk.AutoCAD.ApplicationServices.Application.Invoke(args);

// print the return value
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("result.toString()");

}

 

I wrote a simple LISP function to test it that looks like this:

 

(DEFUN C:HELLO ()
setq hello "HELLO WORLD"
)

 

However, upon calling TEST in AutoCAD it throws an invalidInput error on my Invoke call. 

Tags (3)
Message 5 of 25
_gile
in reply to: Anonymous

If your LISP function is as above (there're missing parents in the one you posted):

 

(DEFUN C:HELLO ()
  (setq hello "HELLO WORLD")
)

It requires none argument, so to call it from .NET, the argument for Application.invoke() should only contains the LISP function name: "C:HELLO" here.

 

CommandMethod("Test", CommandFlags.Modal)]
public void Test()
{

    // build the arguments list
    ResultBuffer args = new ResultBuffer(
new TypedValue((int)LispDataType.Text, "C:HELLO")); // call the LISP fuction and get the return value ResultBuffer result = Application.Invoke(args); // print the return value Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage(result.ToString()); }

 

You may read the LISP docs for (vl-acad-defun)  and the .NET ones for Application.Invoke().

 

PS: if you want to see the LISP function return value at the commande prompt, do not quote result.Tostring() in the last line of upper code.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 6 of 25
Anonymous
in reply to: _gile

All arguments but "Hello" were commented out in my last post. Does the function have to start with C: or can it just be called HELLO?

Message 7 of 25
_gile
in reply to: Anonymous

To be able to invoke a LISP function from an external ObjectARX or .NET application, you have to prefix the LISP function name with "C:" (in this case, this prefix is part of the function name) or register it with vl-acad-defun (please read the help doc for this function).



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 8 of 25
Anonymous
in reply to: _gile

I appreciate all your help on this. Right now my method looks like this

 

[CommandMethod("Test", CommandFlags.Modal)]
public void Test()
{

// build the arguments list
ResultBuffer args = new ResultBuffer(new TypedValue((int)LispDataType.Text, "HELLO"));

// call the LISP fuction anf get the return value
ResultBuffer result = Autodesk.AutoCAD.ApplicationServices.Application.Invoke(args);

// print the return value
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage(result.ToString());
}

 

and my LISP file looks like this

 

(vl-acad-defun HELLO ()
setq hello "HELLO WORLD"
)

 

When I run it, it pops this error message

 

Capture.PNG

 

I don't understand what I'm missing. I looked at the help document you linked and it didn't give any indication I missed something

 

Tags (3)
Message 9 of 25
_gile
in reply to: Anonymous

I showed an example of (vl-acad-defun) in my first reply.

 

Using the "c:" prefix

 

LISP function:

(defun c:hello () 
(setq hello "HELLO WORLD")
)

 C# code

[CommandMethod("Test", CommandFlags.Modal)]
public void Test()
{
    ResultBuffer args = new ResultBuffer(
        new TypedValue((int)LispDataType.Text, "c:hello"));
    ResultBuffer result = Application.Invoke(args);
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
    ed.WriteMessage(result.ToString());
}

 

Using (vl-acad-defun)

 

LISP code:

(defun hello () 
  (setq hello "HELLO WORLD")
)
 
(vl-acad-defun 'hello)

 C# code

[CommandMethod("Test", CommandFlags.Modal)]
public void Test()
{
    ResultBuffer args = new ResultBuffer(
        new TypedValue((int)LispDataType.Text, "hello"));
    ResultBuffer result = Application.Invoke(args);
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
    ed.WriteMessage(result.ToString());
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 10 of 25
viper_007
in reply to: _gile

You really do me a big favor!
聚傲气于一身,显傲骨之精华
Message 11 of 25
ganderson
in reply to: _gile

I have a really simple question about your code. Where does the  LISP code go in your C# program. I see the function in C# where you invoke the LISP function, but where do you put the actual code:

(defun c:hello () 
(setq hello "HELLO WORLD")
)?
Thanks, really struggling here!
~Vonnie
Tags (1)
Message 12 of 25
Anonymous
in reply to: ganderson

Its been a little while since I looked at it but I believe the .lsp file either has to be in the same directory as the c# code and/or the lisp code has to be loaded via APPLOAD
Message 13 of 25
ganderson
in reply to: Anonymous

So if the .lsp file is in the same directory as the C# code, do I need to
somehow "include" the file name in the C# file?
Thanks,
~Vonnie
Message 14 of 25
fieldguy
in reply to: ganderson

Pay close attention to giles answer (msg 2 in this thread).

 

The first element in "args" is the name of the lisp command "foo" - the definition of foo is shown in the comments (defun foo).

 

Then you use Application.Invoke(args) to actually run the lisp.  If foo.lsp is found, it will execute and return the resultbuffer.

Message 15 of 25
_gile
in reply to: fieldguy

Hi,

 

The LISP file path doesn't matter.

As for any other way to call a LISP function, the LISP file have to be loaded in the drawing before you can run it.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 16 of 25
ganderson
in reply to: _gile

I found this out. I had to do an appload and load foo.lsp before test would
work.
Thanks,
~Vonnie
Message 17 of 25
juanma9886
in reply to: _gile

Hi Gilles,

 

I want to call this lisp 

 

(defun c:hello ()
(command "_circle" "0,0" "3,3")
(princ)
)

 

 

My question is:

 

 

What kind of lispdatatype  i need to use for this function defined.

 

 

I will appreciate your help

 

 

Message 18 of 25
_gile
in reply to: juanma9886

Hi,

 

As the LISP function have no argument, the ResultBuffer must only contain the LISP function name (c:hello) which i a text (string)..

 

Application.Invoke(new ResultBuffer(new TypedValue((int)LispDataType.Text, "c:hello")));

But, one more time, most of the time it's much simpler to convert LISP routines into .NET than trying to solve the problems due to calling LISP from .NET.

I totally agree with @dgorsman's replies in this topic.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 19 of 25
Anonymous
in reply to: _gile

Hi _gile!

I have copied this code to my project, but i had an error - "Application" does not contain a definition for "Invoke"".

I have set links to libraries - AcMgd  and AcDbMgd, Framework v.3.5 (for Autocad 2009).

Maybe Framework 3.5 doesn't support this method?

And what is another way to run LISP from C#?

 

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace ClassLibrary4
{
    public class Class1
    {
        [CommandMethod("Test", CommandFlags.Modal)]
        public void Test()
        {
            ResultBuffer args = new ResultBuffer(
                new TypedValue((int)LispDataType.Text, "c:hello"));
            ResultBuffer result = Application.Invoke(args);
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            ed.WriteMessage(result.ToString());
        }
    }
}

 

Message 20 of 25
ActivistInvestor
in reply to: Anonymous

I don't recall what release it showed up in, but in earlier releases, there was no Application.Invoke.

 

In that case, you have to P/Invoke the acedInvoke() method.

 

Searching this forum on acedInvoke() should turn up code that shows it its done.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost