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

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

本帖最后由 革天明 于 2015-10-12 14:04 编辑

李冠亿老师《深入浅出AutoCAD.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<System::Reflection::MethodInfo ^>* 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:24

为什么这样用!

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

ivde 发表于 2015-10-12 18:19 static/image/common/back.gif
为什么这样用!

请教如何用才对?

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

革天明 发表于 2015-10-13 08:56 static/image/common/back.gif
请教如何用才对?
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:47

在XP 、CAD2007能运行。

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

ivde 发表于 2015-10-13 10:13 static/image/common/back.gif
class CH6_8_3 用 public class CH6_8_3

using System;


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:10

yshf 发表于 2015-10-13 15:43 static/image/common/back.gif
在XP 、CAD2007能运行。

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

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

革天明 发表于 2015-10-13 15:54 static/image/common/back.gif
目前已知2007、2010、2011、2014下没有问题,2008的有点特殊,6楼为2008的正确代码

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

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

ivde 发表于 2015-10-13 16:07 static/image/common/back.gif
void 是没有返回值的,alisp 好像都需要一个返回值

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

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

本帖最后由 ivde 于 2015-10-13 17:37 编辑

革天明 发表于 2015-10-13 16:28 static/image/common/back.gif
好像是这个原因,请问如何定义一个.NET函数,参数为int a和int b,结果为a*b,这样的函数如何写?最终还是 ...

      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,否则就要 区分
if (arg.Length==2 && (arg.TypeCode==5001 ||arg.TypeCode==5003 || arg.TypeCode==5010)
                && (arg.TypeCode == 5001 || arg.TypeCode == 5003 || arg.TypeCode == 5010))
            {
                var num1 = arg.Value;
                var num2 = arg.Value;
                var result = (double)num1 + (double)num2;
                return result;
            }
页: [1] 2
查看完整版本: Lisp与.NET互相调用。CAD2008 .net程序运行出现异常,请各位老师找出出错原因,非...