Dino:

I tried using the PythonDelegateWrapper you posted below with the same
results. To make things easier I tried moving all my testing into a
single C# file and have it run the code from C# instead of a compiling
a python file. Below is the code. When I execute "regtest" in AutoCAD
it fatal errors on me. I also added
System.Environment.SetEnvironmentVariable("COMPlus_MDA", "1"); to the
initialize of my code but it doesn't do anything for me. Any other
ideas?

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

using IronPython.Hosting;

namespace PyAcadDotNet
{
        /// <summary>
        /// PyAcadCmd Class:
        /// Used to register commands on the AutoCAD command stack.
        /// </summary>
        public class PyAcadCmd
        {
                public PyAcadCmd()
                {
                }
                public delegate void CmdDelegate();
        internal delegate void AddReference(object assembly);

                /// <summary>
                /// RegPyAcadCmd:
                /// Registers a delegate (callback) with the AutoCAD command 
string
                /// on the command stack.
                /// </summary>
        [DllImport("PyRegCmd.dll",
                         CallingConvention=CallingConvention.Cdecl,CharSet = 
CharSet.Unicode,
                         EntryPoint = "?RegPyCmd@@[EMAIL PROTECTED]")]
                public static extern void RegPyCmd(
                        string cmd_group,
                        string cmd_name,
                        Autodesk.AutoCAD.Runtime.CommandFlags cmd_flags,
                        [MarshalAs(UnmanagedType.FunctionPtr)] CmdDelegate 
cmd_delegate);


        public static void PythonRegister(string CommandName,
CmdDelegate FuncPointer, CommandFlags flags)
        {
            RegPyCmd("_pycmds", CommandName, flags, new
CmdDelegate(new PythonDelegateWrapper(FuncPointer).Invoke));
        }

        //testing stuff
        public static void testcommand()
        {
            Editor ed =
Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
            ed.WriteMessage("\ncb1 delegate seems to work!\n");
        }
        [CommandMethod("regcmds")]
        static public void test() // This method can have any name
        {
            CmdDelegate cb1 = new CmdDelegate(PyAcadCmd.testcommand);
            PythonRegister("testcommand", cb1, CommandFlags.Session);
        }
        [CommandMethod("regtest", CommandFlags.Session)]
        static public void regtest()
        {
            PythonEngine engine = new PythonEngine();
            engine.Import("clr");
            AddReference adr =
engine.CreateMethod<AddReference>("clr.AddReference(assembly)");
            adr(typeof(BlockTableRecord).Assembly);
            adr(typeof(Editor).Assembly);
            CompiledCode cc = engine.Compile(
                @"
import Autodesk.AutoCAD.Runtime
import clr
clr.AddReference('PyAcadDotNet')
from PyAcadDotNet import PyAcadCmd
def foo():
    print 'hello world'
PyAcadCmd.PythonRegister('pythontester', foo,
Autodesk.AutoCAD.Runtime.CommandFlags.Session)");
            cc.Execute();
        }
        }

    class PythonDelegateWrapper
    {
        private PyAcadCmd.CmdDelegate cmdDelegate;
        public PythonDelegateWrapper(PyAcadCmd.CmdDelegate dlg)
        {
            cmdDelegate = dlg;
        }
        public void Invoke()
        {
            cmdDelegate();
        }
    }
}
********code**********



On 8/30/07, Dino Viehland <[EMAIL PROTECTED]> wrote:
> Well at this point we've successfully created the delegate and passed it off 
> to you so it's hard to tell what's going wrong here.  Couple of suggestions 
> on things to try and troubleshoot the issue:
>         Instead of handing the delegate you get off to the P/Invoke call can 
> you just turn around and invoke the delegate from C# code and successfully 
> call back into the Python code?
>         If that works can you do something like:
>
> class PythonDelegateWrapper {
>         private CmdDelegate cmdDelegate;
>         public PythonDelegateWrapper(CmdDelegate dlg) {
>                 cmdDelegate = dlg;
>         }
>
>         public void Invoke() {
>                 cmdDelegate();
>         }
> }
>
> And then pass "new CmdDelegate(new PythonDelegateWrapper(dlg).Invoke)" to the 
> P/Invoke function?
>
> The reason why I'm proposing this is maybe there's a strange interaction 
> between dynamic methods (which the Python delegate will be) and the P/Invoke 
> call - this might help isolate the issue.
>
> And the final thing that might be interesting to try would be to make sure 
> you keep the reference to the delegate alive during the lifetime of the call. 
>  In theory this should be happening for you automatically -   but if the 
> unmanaged side is going to hold onto this delegate for longer than the 
> duration of the call you'll need to do this anyway.  Given that you're still 
> in the call this shouldn't be an issue but you could set the environment 
> variable COMPlus_MDA=1 to enable CLR Managed Debugging Assistants to see if 
> you get any warnings about that firing.  I don't really believe this could be 
> happening but it would be consistent w/ the exception you're getting.
>
> Those are my 1st two guesses as to what could be going wrong, hopefully one 
> of them will be helpful :).
>
> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Tim Riley
> Sent: Thursday, August 30, 2007 8:59 AM
> To: Discussion of IronPython
> Subject: Re: [IronPython] Hosting: Delegates from Ironpython to C#
>
> Dino:
>
> I was trying something similar to what you had posted and was getting
> an error. I also just tried the code you gave me with a minor
> correction to fix the CommandFlags part and received the error below.
> If it helps I have also added the C# code use to call the python file
> below the error if that will help at all.
>
>
> *********ERROR***********
> Command: pyfile
> System.AccessViolationException: Attempted to read or write protected memory.
> This is often an indication that other memory is corrupt.
>    at PyAcadDotNet.PyAcadCmd.RegPyCmd(String cmd_group, String cmd_name, 
> CommandFlags cmd_flags, CmdDelegate cmd_delegate)
>    at PyAcadDotNet.PyAcadCmd.PythonRegister(String CommandName, CmdDelegate 
> FuncPointer, CommandFlags flags) in C:\Documents and Settings\TJRiley\My 
> Documents\pyacaddotnet\registercommand.cs:line 65
>    at PythonRegister##20(Object , Object , Object )
>    at IronPython.Runtime.Calls.CallTarget3.Invoke(Object arg0, Object arg1, 
> Object arg2)
>    at IronPython.Runtime.Calls.FastCallable3.Call(ICallerContext context, 
> Object arg0, Object arg1, Object arg2)
>    at IronPython.Runtime.Calls.BuiltinFunction.Call(ICallerContext context, 
> Object arg0, Object arg1, Object arg2)
>    at IronPython.Runtime.Operations.Ops.CallWithContext(ICallerContext 
> context, Object func, Object arg0, Object arg1, Object arg2)
>    at C:\Documents and Settings\TJRiley\My 
> Documents\pyacaddotnet\Samples\commandmethod_test.py##22(ModuleScope )
>    at IronPython.Hosting.CompiledCodeDelegate.Invoke(ModuleScope moduleScope)
>    at IronPython.Hosting.CompiledCode.Run(ModuleScope moduleScope)
>    at IronPython.Hosting.CompiledCode.Execute(EngineModule engineModule, 
> IDictionary`2 locals)
>    at IronPython.Hosting.CompiledCode.Execute()
>    at PyAcadDotNet.AcadInterface.pythonfile() in C:\Documents and
> Settings\TJRiley\My Documents\pyacaddotnet\PyAcadDotNet.cs:line 98
> *********ERROR***********
>
>
> *********CODE**************
> using System;
> using System.Collections;
> using System.Windows.Forms;
> using System.IO;
> using System.Text;
> using System.Runtime.InteropServices;
>
> using Autodesk.AutoCAD.ApplicationServices;
> using Autodesk.AutoCAD.DatabaseServices;
> using Autodesk.AutoCAD.Runtime;
> using Autodesk.AutoCAD.EditorInput;
>
> using AcEd = Autodesk.AutoCAD.EditorInput;
> using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
>
> using IronPython.Hosting;
>
> namespace PyAcadDotNet
> {
>   public class AcadInterface : IExtensionApplication
>   {
>     static internal AcEd.Editor ed =
> AcadApp.DocumentManager.MdiActiveDocument.Editor;
>
>     public delegate void TestDelegate();
>
>
>     public void Initialize()
>     {
>       ed.WriteMessage("\nPyAcad.NET Loaded Successfully....");
>       ed.WriteMessage("\ntype 'pyhelp' for commands....");
>     }
>
>     public void Terminate()
>     {
>       this.Terminate();
>     }
>
>     internal delegate void AddReference(object assembly);
>
>     [CommandMethod("pyfile", CommandFlags.Session)]
>     static public void pythonfile()
>     {
>       using (PythonEngine engine = new PythonEngine())
>       {
>         using (AcadCommandLine myCommandLine = new AcadCommandLine())
>         {
>           try
>           {
>             // Create a new instance of PythonEngine and set variables.
>             engine.AddToPath(Environment.CurrentDirectory);
>             // Send Stdout and Stderr to the AutoCAD command line.
>             engine.SetStandardOutput(myCommandLine);
>             engine.SetStandardError(myCommandLine);
>             engine.Import("clr");
>             PyAcadCmd regcmds = new PyAcadCmd();
>             engine.Globals.Add("regcmds", regcmds);
>             //lets load some AutoCAD assemblies.
>             AddReference adr =
> engine.CreateMethod<AddReference>("clr.AddReference(assembly)");
>             adr(typeof(BlockTableRecord).Assembly);
>             adr(typeof(Editor).Assembly);
>
>             // Display an OpenFileDialog and run the script.
>             OpenFileDialog ofd = new OpenFileDialog();
>             ofd.Filter = "Python files (*.py)|*.py|All files (*.*)|*.*";
>             ofd.ShowDialog();
>
>             // Run the file selected by the open file dialog box.
>             //engine.ExecuteFile(ofd.FileName);
>             CompiledCode cc = engine.CompileFile(ofd.FileName);
>             cc.Execute();
>           }
>           catch (System.Exception e)
>           {
>             ed.WriteMessage(e.ToString());
>           }
>         }
>       }
>     }
>  }
>
>   //
>   public class AcadCommandLine : Stream
>   //Modified version of a class coded by Mike Stall.
>   {
>     public AcadCommandLine()
>     {
>       //constructor
>     }
>
>     #region unsupported Read + Seek members
>     public override bool CanRead
>     {
>       get { return false; }
>     }
>
>     public override bool CanSeek
>     {
>       get { return false; }
>     }
>
>     public override bool CanWrite
>     {
>       get { return true; }
>     }
>
>     public override void Flush()
>     {
>       //
>     }
>
>     public override long Length
>     {
>       get { throw new NotSupportedException("Seek not supported"); }
> // can't seek
>     }
>
>     public override long Position
>     {
>       get
>       {
>         throw new NotSupportedException("Seek not supported");  // can't seek
>       }
>       set
>       {
>         throw new NotSupportedException("Seek not supported");  // can't seek
>       }
>     }
>
>     public override int Read(byte[] buffer, int offset, int count)
>     {
>       throw new NotSupportedException("Reed not supported"); // can't read
>     }
>
>     public override long Seek(long offset, SeekOrigin origin)
>     {
>       throw new NotSupportedException("Seek not supported"); // can't seek
>     }
>
>     public override void SetLength(long value)
>     {
>       throw new NotSupportedException("Seek not supported"); // can't seek
>     }
>     #endregion
>
>     public override void Write(byte[] buffer, int offset, int count)
>     {
>       try
>       {
>         // Very bad hack: Ignore single newline char. This is because
> we expect the newline is following
>         // previous content and we already placed a newline on that.
>         AcEd.Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
>
>         if (count == 1 && buffer[offset] == '\n')
>           return;
>
>         StringBuilder sb = new StringBuilder();
>         while (count > 0)
>         {
>           char ch = (char)buffer[offset];
>           if (ch == '\n')
>           {
>             ed.WriteMessage(sb.ToString() + "\n");
>             sb.Length = 0; // reset.
>           }
>           else if (ch != '\r')
>           {
>             sb.Append(ch);
>           }
>
>           offset++;
>           count--;
>         }
>         if (sb.Length > 0)
>           ed.WriteMessage(sb.ToString() + "\n");
>       }
>       catch (System.Exception e)
>       {
>         throw e;
>       }
>     }
>   }
> }
> *********CODE**************
> On 8/30/07, Dino Viehland <[EMAIL PROTECTED]> wrote:
> > I think you should be able to just pass a function object to PythonRegister 
> > and it should be converted into a delegate.  For example:
> >
> > import clr
> > clr.AddReference('PyAcadDotNet')
> > from PyAcadDotNet import PyAcadCmd
> >
> > def foo():
> >         print 'hello world'
> >
> > PyAcadCmd.PythonRegister('some command', foo, CommandFlags.Whatever)
> >
> > Does that not work?
> >
> > -----Original Message-----
> > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Tim Riley
> > Sent: Wednesday, August 29, 2007 7:10 PM
> > To: Discussion of IronPython
> > Subject: [IronPython] Hosting: Delegates from Ironpython to C#
> >
> > I'm embedding IronPython in a C# dll that is hosted inside a program
> > called AutoCAD. In order to register commands in AutoCAD from .NET I
> > need to P/Invoke a C function inside a .dll. I can do this fairly easy
> > from C# but I can't figure out the right way to call my C# wrapper
> > from IronPython to have it register the command. I have perused the
> > hosting docs for 1.1 and haven't been able to come up with a solution
> > that works. Here is my C# code. I either want to call the PyRegCmds
> > void or the PythonRegister void.  Both of which expect a delegate.for
> > example if I had a python function like:
> >
> > def test1:
> >     print "This is a test".
> >
> > I can't figure out how to map test to the delegate required in the code 
> > below.
> > Note: I can call this from C# fine. See :static public void test().
> >
> > Can anyone give me any pointers? It would be greatly appreciated.
> >
> >
> > code:
> >
> > using System ;
> > using System.Runtime.InteropServices;
> > using Autodesk.AutoCAD.Runtime ;
> > using Autodesk.AutoCAD.EditorInput;
> >
> > namespace PyAcadDotNet
> > {
> >         /// <summary>
> >         /// PyAcadCmd Class:
> >         /// Used to register commands on the AutoCAD command stack.
> >         /// </summary>
> >         public class PyAcadCmd
> >         {
> >                 public PyAcadCmd()
> >                 {
> >                 }
> >                 public delegate void CmdDelegate();
> >
> >                 /// <summary>
> >                 /// RegPyAcadCmd:
> >                 /// Registers a delegate (callback) with the AutoCAD 
> > command string
> >                 /// on the command stack.
> >                 /// </summary>
> >         [DllImport("PyRegCmd.dll",
> >                          CallingConvention=CallingConvention.Cdecl,CharSet 
> > = CharSet.Unicode,
> >                          EntryPoint = "?RegPyCmd@@[EMAIL PROTECTED]")]
> >                 public static extern void RegPyCmd(
> >                         string cmd_group,
> >                         string cmd_name,
> >                         Autodesk.AutoCAD.Runtime.CommandFlags cmd_flags,
> >                         [MarshalAs(UnmanagedType.FunctionPtr)] 
> > PyAcadCmd.CmdDelegate cmd_delegate);
> >
> >
> >         public static void PythonRegister(string CommandName,
> > CmdDelegate FuncPointer, CommandFlags flags)
> >         {
> >             RegPyCmd("_pycmds", CommandName, flags, FuncPointer);
> >         }
> >
> >         //testing stuff
> >         public static void testcommand()
> >         {
> >             Editor ed =
> > Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
> >             ed.WriteMessage("\ncb1 delegate seems to work!\n");
> >         }
> >         [CommandMethod("regcmds")]
> >         static public void test() // This method can have any name
> >         {
> >             CmdDelegate cb1 = new CmdDelegate(PyAcadCmd.testcommand);
> >             PythonRegister("testcommand", cb1, CommandFlags.Session);
> >         }
> >         }
> >
> >
> > }
> > _______________________________________________
> > Users mailing list
> > [email protected]
> > http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
> > _______________________________________________
> > Users mailing list
> > [email protected]
> > http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
> >
> _______________________________________________
> Users mailing list
> [email protected]
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
> _______________________________________________
> Users mailing list
> [email protected]
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
_______________________________________________
Users mailing list
[email protected]
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com

Reply via email to