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