Author Topic: Expose ARX Function to .NET  (Read 36892 times)

0 Members and 2 Guests are viewing this topic.

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Expose ARX Function to .NET
« Reply #30 on: August 26, 2007, 03:57:12 AM »
Well, from that discussion Tim, the link I gave above in post 24 would be the way to go.

The guts of what you are trying to do is pass an address (pointer in C terms) of a function for autocad to call when someone enters the command string, basically like a Python dictionary, ie. 'call the function (go to the address) that is stored at this key (the command string)'.
The biggest problem is converting a clr address to a native address for native code to call, not only that is has to be there for the whole acad session, making your managed delegate static 'should' ensure that to an extent but I don't know for sure.

I would still give P/Invoke a go, you still need to make a delegate regardless and it's an easy exercise, if that doesn't work then the link I mentioned is probably your best chance.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8662
  • AKA Daniel
Re: Expose ARX Function to .NET
« Reply #31 on: August 26, 2007, 04:16:26 AM »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8662
  • AKA Daniel
Re: Expose ARX Function to .NET
« Reply #32 on: August 26, 2007, 09:39:34 AM »
Your going to be executing the script itself, and not individual functions within the script correct? cc.execute  runs the whole script right?

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Expose ARX Function to .NET
« Reply #33 on: August 26, 2007, 09:34:35 PM »
Ok, I took the most simple way out (for me anyway) and it seems to work, what you may need to do is have a C# command that asks for and loads you IronPy commands or just add them to a file similar to below, ie. create a delegate for each functions and call RegPyCmd() for each one.
hope it works at your end.

here's the C# code
Code: [Select]
// Created By: Mick Duprez, 27th August 2007
// Test application to test use of acedRegCmds wrapper function in C

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

[assembly: CommandClass(typeof(ClassLibrary.DCSClass))]

namespace ClassLibrary
{
/// <summary>
/// Summary description for DCSClass.
/// </summary>
public class DCSClass
{
public DCSClass()
{
//
// TODO: Add constructor logic here
//
}
public delegate void TestCb();
public static void testcommand()
{
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("\ntest delegate seems to work!\n");
}
// import the dll:
[DllImport("IronPyCmdReg.dll",
CallingConvention=CallingConvention.Cdecl,
EntryPoint = "?RegPyCmd@@YAXPBD0HP6AXXZ@Z")]
public static extern void RegPyCmd(string cmdGroup,
string cmdName,
CommandFlags cmdFlags,
[MarshalAs(UnmanagedType.FunctionPtr)] TestCb functionptr);

// Define Command to register commands without using attributes:
[CommandMethod("regcmds")]
static public void test() // This method can have any name
{
// create the callback
DCSClass.TestCb cb = new DCSClass.TestCb(DCSClass.testcommand);
// PInvoke the RegPyCmd() function:
DCSClass.RegPyCmd("pycmds","testpy",CommandFlags.Session,cb);
}
}
}

The C code -
Code: [Select]
// Created By: Mick Duprez, 27th August 2007
//************ Iron Python Command Register Function ************************//
__declspec(dllexport) void __cdecl RegPyCmd(const char * cmdGroup,
const char * cmdName,
int cmdFlags,
void(*functionptr)())
{
// Note: cast functionptr as AcRxFuctionPtr.
acedRegCmds->addCommand(cmdGroup, cmdName, cmdName, (int)cmdFlags,(AcRxFunctionPtr)functionptr);
}

I've also attached the test C# dll and native dll that is PInvoked, I'll post the 2 solutions when I get a chance (I'm still getting a huge arx sln???). Both dlls' were tested on ac2006.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Expose ARX Function to .NET
« Reply #34 on: August 26, 2007, 09:42:38 PM »
The 2 solutions are attached.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Expose ARX Function to .NET
« Reply #35 on: August 26, 2007, 09:45:47 PM »
And a piccy showing before regcmds was called and after
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

TR

  • Guest
Re: Expose ARX Function to .NET
« Reply #36 on: August 26, 2007, 10:18:57 PM »
Mick, you are great. That looks like exactly what I was looking for. I'll mess with it tomorrow as I'm off to bed now.

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Expose ARX Function to .NET
« Reply #37 on: August 26, 2007, 10:22:39 PM »
Glad to help, now you need to work out a way of calling it when you netload your IronPython dll without using C#!
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

TR

  • Guest
Re: Expose ARX Function to .NET
« Reply #38 on: August 26, 2007, 10:50:16 PM »
Mick:

What exactly am I supposed to be doing with the IronPyCmdReg.dll file? Do I have to register it somehow or put it somewhere on my path? I am getting a Dll Not Found Exception. Also should this dll work with 2008 or do I need to recompile it?

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Expose ARX Function to .NET
« Reply #39 on: August 26, 2007, 10:58:44 PM »
just place the dll where you put the CsMgg---.dll, PInvoke will find it then.
There is no mfc or anything so it 'may' work in 2008, if not it should be trivial to recompile it to ac2008 - unicode may present a problem though??

This was knocked together this morning pretty roughly to see if it was going to work and can now be tidied up and made more suitable for your needs. The reason you can't just PInvoke the acedRegCmds is because it is a macro (it gets expanded during preprocessing into the real code which is another method all together) so it wasn't exported so I just wrapped it in another C function for export.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Expose ARX Function to .NET
« Reply #40 on: August 26, 2007, 11:09:21 PM »
A test using a few callbacks

Code: [Select]
// Created By: Mick Duprez, 27th August 2007
// Test application to test use of acedRegCmds wrapper function in C

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

[assembly: CommandClass(typeof(ClassLibrary.DCSClass))]

namespace ClassLibrary
{
/// <summary>
/// Summary description for DCSClass.
/// </summary>
public class DCSClass
{
public DCSClass()
{
//
// TODO: Add constructor logic here
//
}
public delegate void TestCb();
public static void testcommand1()
{
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("\ncb1 delegate seems to work!\n");
}

public static void testcommand2()
{
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("\ncb2 delegate seems to work!\n");
}

public static void testcommand3()
{
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("\ncb3 delegate seems to work!\n");
}
// import the dll:
[DllImport("IronPyCmdReg.dll",
CallingConvention=CallingConvention.Cdecl,
EntryPoint = "?RegPyCmd@@YAXPBD0HP6AXXZ@Z")]
public static extern void RegPyCmd(string cmdGroup,
string cmdName,
CommandFlags cmdFlags,
[MarshalAs(UnmanagedType.FunctionPtr)] TestCb functionptr);

// Define Command to register commands without using attributes:
[CommandMethod("regcmds")]
static public void test() // This method can have any name
{
// create some callbacks
DCSClass.TestCb cb1 = new DCSClass.TestCb(DCSClass.testcommand1);
DCSClass.TestCb cb2 = new DCSClass.TestCb(DCSClass.testcommand2);
DCSClass.TestCb cb3 = new DCSClass.TestCb(DCSClass.testcommand3);

// PInvoke the RegPyCmd() function:
DCSClass.RegPyCmd("pycmds","testpy1",CommandFlags.Session,cb1);
DCSClass.RegPyCmd("pycmds","testpy2",CommandFlags.Session,cb2);
DCSClass.RegPyCmd("pycmds","testpy3",CommandFlags.Session,cb3);

}
}
}

"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

TR

  • Guest
Re: Expose ARX Function to .NET
« Reply #41 on: August 26, 2007, 11:13:41 PM »
I'll have to figure out what I need to compile your C++ project using Visual C++ Express. I tried copying your C++ dll into the same dir as my dll and I get an exception. When I try to recompile your DLL I get can't find windows.h. I'll take a look tomorrow. Thanks again.

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: Expose ARX Function to .NET
« Reply #42 on: August 26, 2007, 11:28:29 PM »
Sorry, I don't have anything later than vs2002 on this machine.
What you will need is the arx sdk for ac2008, there should be an ARX wizard in the utils folder, install it and that will make it a snap although you may still need to add the paths to the include and lib directories of the project (under the C++ and linker dir's - Add additional lib/inc directories), I didn't have to add any lib's for arx as the wizard took care of them I think.

Just copy and paste the function in the top (under the 'includes') of the acrxentrypnt.cpp or similar, as long as it's not in the scope of a class.
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8662
  • AKA Daniel
Re: Expose ARX Function to .NET
« Reply #43 on: August 27, 2007, 02:20:09 AM »
See if this works

Netload the PyAcad dll file for AC2008 in the zip file
run the PyLoad command at the prompt
load one of the .py files from the zip file
at the top of the py file is the command I.e #@$winform
a new command called winform should be registered

run the winform form command.

Deleted the zip file if your machine crashes  :-D


« Last Edit: August 27, 2007, 12:49:25 PM by Danielm103 »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8662
  • AKA Daniel
Re: Expose ARX Function to .NET
« Reply #44 on: August 27, 2007, 06:21:17 AM »
Here is the source/.dll/solution,

Basically what it does is,
Reads the first line of the .py file the registers the command.
Stores a copy of the command and the path to the py file in a dictionary.
A reactor fires when you type a command that’s in the dictionary, invoking a copy of your pyfile command.

At first I was storing the command and a copy of the compiled code in a hashtable, which is faster than compiling the .py file each time, but it was unstable (I don’t know the internal workings of IronPython)

I ported all of your C# Code to C++/CLI and stuck it in the assembly

This should be a great foundation for you to build on, as you can use mix native/managed code. You can stick Mick’s code in there as well.
« Last Edit: August 27, 2007, 12:49:58 PM by Danielm103 »