Dino:
I revised the code to what you suggested and still no luck.

Is there any way I can set the environment variable other than via the
command prompt? My application is hosted inside another application
and I can't set the variable from there.

Tim

On 8/30/07, Dino Viehland <[EMAIL PROTECTED]> wrote:
> Setting the env var at runtime won't help, you'll want to set it at a command 
> prompt and start your app from the command prompt.  One other tweak:
>
>         public static void PythonRegister(string CommandName,
> CmdDelegate FuncPointer, CommandFlags flags)
>         {
>         PythonDelegateWrapper pdw = new PythonDelegateWrapper(FuncPointer));
>             RegPyCmd("_pycmds", CommandName, flags, new
> CmdDelegate(pdw.Invoke);
>                 GC.KeepAlive(pdw);
>         }
>
> Which will ensure it's not a delegate getting collected issue.
>
> If that doesn't work then we'll need to go into unmanaged debugging territory 
> w/ windbg/cdb/ntsd :).
>
> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Tim Riley
> Sent: Thursday, August 30, 2007 11:55 AM
> To: Discussion of IronPython
> Subject: Re: [IronPython] Hosting: Delegates from Ironpython to C#
>
> 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
> _______________________________________________
> 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