革天明 发表于 2015-10-12 13:43:00

Lisp与.NET互相调用。CAD2008 .net程序运行出现异常,请各位老师找出出错原因,非...

李冠亿老师《深入浅出.NET二次开发》中6.8.3章节经出了一个Lisp与.NET程序互相调用的例子,如下:
/////////////////////////////////////////////////////////////////////////////////////////////////
//http://www.bimcad.org 数字建筑
//深入浅出AutoCAD二次开发(李冠亿)
/////////////////////////////////////////////////////////////////////////////////////////////////
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using System.Runtime.InteropServices;

namespace Sample
{
    class CH6_8_3
    {
      
      private static extern int acedInvoke(IntPtr args, out IntPtr result);
      public static ResultBuffer InvokeLisp(ResultBuffer args, ref int stat)
      {
            IntPtr rb = IntPtr.Zero;
            stat = acedInvoke(args.UnmanagedObject, out rb);
            if (stat == (int)PromptStatus.OK && rb != IntPtr.Zero)
                return (ResultBuffer)DisposableWrapper.Create(typeof(ResultBuffer), rb, true);
            return null;
      }
      
      public void CallLispFunction()
      {
            ResultBuffer args = new ResultBuffer();
            int stat = 0;
            args.Add(new TypedValue((int)LispDataType.Text, "c:CallByNet"));
            ResultBuffer res = InvokeLisp(args, ref stat);
      }
      
      public static void CallByLispFunction(ResultBuffer rbArgs)
      {
            foreach (TypedValue rb in rbArgs)
                if (rb.TypeCode == (int)Autodesk.AutoCAD.Runtime.LispDataType.Text)
                  Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(rb.Value.ToString());
      }
    }
}
并给出了对应的lisp文件的代码:
(defun c:CallByNet()
(setq p1 (getpoint"输入第一点:"))
(setq p2 (getpoint"输入第二点:"))
(command "line" p1 p2 "")
)
(defun c:CallNet()
(setq t1 "BimCad.org")
(setq t2 "数字建筑")
(CallByLispFunction t1 t2)
)
我在测试过程中发现.NET调用lisp的函数Calllispfunction可正常运行,但使用lisp调用.NET的CallNET命令出现异常,错误如下:
命令: callnet
System.ArgumentException: 绑定到目标方法时出错。
   在 System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo
method, Boolean throwOnBindFailure)
   在 AcMgCommandClass.InvokeWorker(AcMgCommandClass* , MethodInfo mi, Object
commandObject, Boolean bLispFunction)
   在 AcMgCommandClass.InvokeWorkerWithExceptionFilter(AcMgCommandClass* ,
MethodInfo mi, Object commandObject, Boolean bLispFunction)
   在 AcMgCommandClass.Invoke(AcMgCommandClass* ,
gcroot* mi, Boolean bLispFunction)
   在 AcMgCommandClass.CommandThunk.InvokeLisp(CommandThunk* ); 错误: ADS 请求错误
原以为是CAD2008安装过程中出现的msxml6.dll不能更新的错误,但重装系统及下载微软msxml6_x86(1.3M)修复后也是同样的错误,经网友确认CAD2011、2014下可正确运行,也说明李老师给的代码是可行的,但现在我的电脑上出现上面的错误,导致程序不能正常运行,请各位指点一下如何才能用Lisp调用.NET的函数。
本人运行环境如下:GHOST XP(32位)SP3,CAD2008(32位),

ivde 发表于 2015-10-12 18:19:00

为什么这样用!

革天明 发表于 2015-10-13 08:56:00


请教如何用才对?

ivde 发表于 2015-10-13 10:13:00


class CH6_8_3 用 public class CH6_8_3
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using System.Runtime.InteropServices;


namespace Sample
{
    public class MyPlugin : IExtensionApplication
    {
      void IExtensionApplication.Initialize()
      {
         
      }
      void IExtensionApplication.Terminate()
      {
            
      }
    }
    public class CH6_8_3
    {
      
      private static extern int acedInvoke(IntPtr args, out IntPtr result);
      public static ResultBuffer InvokeLisp(ResultBuffer args, ref int stat)
      {
            IntPtr rb = IntPtr.Zero;
            stat = acedInvoke(args.UnmanagedObject, out rb);
            if (stat == (int)PromptStatus.OK && rb != IntPtr.Zero)
                return (ResultBuffer)DisposableWrapper.Create(typeof(ResultBuffer), rb, true);
            return null;
      }
      
      public void CallLispFunction()
      {
            ResultBuffer args = new ResultBuffer();
            int stat = 0;
            args.Add(new TypedValue((int)LispDataType.Text, "c:CallByNet"));
            ResultBuffer res = InvokeLisp(args, ref stat);
      }
      
      public static void CallByLispFunction(ResultBuffer rbArgs)
      {
            foreach (TypedValue rb in rbArgs)
                if (rb.TypeCode == (int)Autodesk.AutoCAD.Runtime.LispDataType.Text)
                  Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(rb.Value.ToString());
      }
    }
}

yshf 发表于 2015-10-13 15:43:00

在XP 、CAD2007能运行。

革天明 发表于 2015-10-13 15:52:00


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


namespace Lisp2NET
{
    public class MyPlugin : IExtensionApplication
    {
      void IExtensionApplication.Initialize()
      {
         
      }
      void IExtensionApplication.Terminate()
      {
            
      }
    }
    class CH6_8_3
    {
      
      private static extern int acedInvoke(IntPtr args, out IntPtr result);
      public static ResultBuffer InvokeLisp(ResultBuffer args, ref int stat)
      {
            IntPtr rb = IntPtr.Zero;
            stat = acedInvoke(args.UnmanagedObject, out rb);
            if (stat == (int)PromptStatus.OK && rb != IntPtr.Zero)
                return (ResultBuffer)DisposableWrapper.Create(typeof(ResultBuffer), rb, true);
            return null;
      }
      
      public void CallLispFunction()
      {
            ResultBuffer args = new ResultBuffer();
            int stat = 0;
            args.Add(new TypedValue((int)LispDataType.Text, "c:CallByNet"));
            ResultBuffer res = InvokeLisp(args, ref stat);
      }
      
      public static stringCallByLispFunction(ResultBuffer rbArgs)
      {
            foreach (TypedValue rb in rbArgs)
                if (rb.TypeCode == (int)Autodesk.AutoCAD.Runtime.LispDataType.Text)
                  Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(rb.Value.ToString());
            return "";
      }
    }
}
以上修改源于EDATA,指明CAD2008时函数返回值不能空(lisp函数至少会返回一个nil)
XP SP3 CAD2008 sp1 VS2010 .net 2.0下测试通过,谢谢EDATA!

革天明 发表于 2015-10-13 15:54:00


目前已知2007、2010、2011、2014下没有问题,2008的有点特殊,6楼为2008的正确代码

ivde 发表于 2015-10-13 16:07:00


void 是没有返回值的,alisp 好像都需要一个返回值

革天明 发表于 2015-10-13 16:28:00


好像是这个原因,请问如何定义一个.NET函数,参数为int a和int b,结果为a*b,这样的函数如何写?最终还是想让lisp调用的

ivde 发表于 2015-10-13 16:55:00



      public static object MyAdd(ResultBuffer rbArgs)
      {
            var arg = rbArgs.AsArray();
            if (arg.Length==2 && arg.TypeCode==(int)LispDataType.Double && arg.TypeCode==(int)LispDataType.Double)
            {
                var num1 = (double)arg.Value;
                var num2 = (double)arg.Value;
                Double result = num1 + num2;
                return result;
            }
            else {
                return null;
            }
      }
C# 是区分类型的,Acad 用到的有 5001 5003 5010 ,简单的结果转为 double,否则就要 区分复制代码
页: [1]
查看完整版本: Lisp与.NET互相调用。CAD2008 .net程序运行出现异常,请各位老师找出出错原因,非...