zoukankan      html  css  js  c++  java
  • [翻译]ObjectArx.Net下Invoke非托管的函数

    Invoking Unmanaged Methods from AutoCAD's .NET API

    Invoking Unmanaged Methods from AutoCAD's .NET API

    One of the greatest strength's of Autodesk's AutoCAD software is the extensive API access provided by the product.  For years now, it has been very common to use Lisp or VBA to extend the functionality of the various AutoCAD products in numerous ways.  However, recent years have seen the introduction of the Common Language Runtime (CLR) from Microsoft, and the introduction of a variety of programming languages that access this CLR via Microsoft's .NET Frameworks.  The most-popular of these languages include Visual Basic and C-Sharp.

    The ability to program in a high-level language like Visual Basic or C-Sharp, along with the extensive support provided by the runtime system through the .NET frameworks, provides significant benefits to application developers.  One of these benefits is the ability to create "managed code", which reduces the complexities involved in managing computer resources.  As a result, Autodesk has provided a "managed API" that can be used to customize AutoCAD from a .NET environment.

    Unfortunately, the managed API fails to expose all of the functionality available in the ObjectARX libraries.  From time to time, it may be necessary for you to access this "hidden" functionality from a C#.NET or VB.NET program.  This article illustrates one way to accomplish this task.  All examples are provided in C-Sharp, but it should be relatively easy to translate them to any other .NET language.

    介绍Autodesk使用Microsoft's .NET Frameworks托管,但是有一部分函数ObjectARX库中有的还没有开放到托管API。 以下为C#实例。

    Preparing the Environment

    In order to access the various entry points exposed to ObjectARX from a .NET language, we must first identify which methods or properties we wish to access, by reading the ObjectARX documentation.  Once we have identified a useful access point, we must identify something called the "mangled" names for the access point.  In order to do this, we will use a tool called dumpbin that should be installed by default when you install your IDE.  For example, dumpbin is installed along with Visual Studio.  If you are using the Express Editions of Visual Studio, you may have to download and install VS Express C++ Edition to get dumbin.

    In order to use dumpbin easily, we want to add the location of the dumpbin.exe file to our Environment Path, so we may run it from any directory.  This may have happened during installation, or you may have to do it yourself.  You can test this to see if it is already setup by starting a Command Prompt window and typing "dumpbin" at the command line.  If you get an error message stating that the command could not be found, then we need to find dumpbin and add its directory to our Environment Path.

    To do that, we'll open up our hard drive in Windows Explorer, then right-click on the "Program Files" directory and select "Search...".  We will then look for "dumpbin".  A sample of the possible results is shown below.

    It looks like there are three versions of dumpbin on this system.  Two of them look like they're for 64-bit systems, but I'm using a 32-bit system, so I'll go with the first one in the list.  We now need to add this directory to the Environment Path.

    To do this, right-click on My Computer and select "Properties", then go to the "Advanced" tab and hit the "Environment Variables" button.  In the lower section of the dialog box ("System variables"), find the "PATH" system variable and hit the "Edit" button.  Now, add the above path to the end of the PATH variable, separated from the path before it by a semi-colon.  Make sure you do not erase or overtype any of the directories already in this path, or you may cause portions of your system to cease to function properly.

    The image below illustrates this process:

    Now, if you go back to the Command Prompt window and type "dumpbin", you should see a list of command options in the window.

    Note that, when you attempt to run dumpbin, you may get a warning message that other files could not be found.  For example, you may get a warning that "mspdb80.dll" could not be found.  If so, follow the same procedure as above.  Locate mspdb80.dll by searching Program Files, then add its directory to the Environment Path (it is probably at "C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE").

    准备工作:1。搜索 dumpbin工具,在Visual Studio安装目录下; 2。(可选步骤,仅为方便CMD下不用录入路径)设置系统路径

    Identifying the "Mangled Name"

    Now that we have configured our environment so that we can run dumpbin, we can use it to identify the mangled name for our desired ObjectARX entry point.  First, by using the ObjectARX documentation, we must identify the method name we wish to access, as well as the DLL that contains the method.

    For this example, we are going to add access to the Scale() and SetScale() methods for the MLeader entity.  These methods are missing from the managed API.  By looking at the ObjectARX documentation, we find the method signatures for the methods:

    Acad::ErrorStatus setScale (double scale);
    double scale() const;

    Now we only need to figure out which DLL contains the access point.  For the most part, the default AutoCAD entities (at least in the 2009 products) are located in the acdb17.dll file located in the AutoCAD install directory.  So let's take a look at the acdb17.dll file, and see what we find.

    By typing simply "dumpbin" at the command line, we can see the various options for the command.  In order to see the various entry points exposed by the API, we must use the "/exports" flag.  Also, if we try doing this on acdb17.dll, we'll get an extremely long list that will probably overrun the screen buffer.  So we will also use the "/out" flag to send the output to a text file we can examine in a text editor.  In order to do this, we type the following command in the command line:

    dumpbin /exports acdb17.dll /out:acdb17dump.txt

    And here is a screenshot of the process.  Note that this image was captured using Civil-3D 2009, but the same basic process applies to any AutoCAD product.  Simply browse to the correct installation directory for the AutoCAD product you are using, and enter the dumpbin command as shown:

    This creates a text file named "acdb17dump.txt" that we can open in any text editor.  If we do so, we'll see an extremely long list of exposed functions.  Scroll down the list until you find the various Scale() methods.  As we can see from the signature, one of these exposed methods is on the MLeader entity - that's the one we want.

    Similarly, we can find the mangled name for the SetScale() method a little further down the list:

    确定要找的函数所在的DLL文件,用 dumpbin /exports acdb17.dll /out:acdb17dump.txt 在命令行窗口输出函数接口道文本。

    Creating the C#.NET Wrappers around the ObjectARX code

    Now that we've identified the mangled names for our access points, we will create C-Sharp methods that invoke our target methods in acdb17.dll.

    View Code
    using System; 
    using System.Runtime.InteropServices;
    using Autodesk.AutoCAD.DatabaseServices;
    using Autodesk.AutoCAD.Runtime;

    namespace DatabaseExtensions
    {
    public class DatabaseExtensions
    {
    private static class AcDbMLeader
    {
    // this line improves performance by relaxing stack traces
    // during the call to the unmanaged code; only need to
    // include this line once for each class
    [System.Security.SuppressUnmanagedCodeSecurity]

    // method sig from ObjectARX:
    // double scale() const;

    [DllImport("acdb17.dll", CallingConvention = CallingConvention.ThisCall, CharSet = CharSet.Unicode, EntryPoint = "?scale@AcDbMLeader@@QBENXZ")]
    public static extern double scale(IntPtr mleader);

    // method sig from ObjectARX:
    // Acad::ErrorStatus setScale (double scale);

    [DllImport("acdb17.dll", CallingConvention = CallingConvention.ThisCall, CharSet = CharSet.Unicode, EntryPoint = "?setScale@AcDbMLeader@@QAE?AW4ErrorStatus@Acad@@N@Z")]
    public static extern ErrorStatus setScale(IntPtr mleader, double scale);
    }

    public static double GetMLeaderScale(MLeader mldr)
    { return AcDbMLeader.scale(mldr.UnmanagedObject); }

    public static void SetMLeaderScale(MLeader mldr, double scale)
    { AcDbMLeader.setScale(mldr.UnmanagedObject, scale); }
    }
    }

    In the code above, the AcDbMLeader subclass encapsulates our calls to the unmanaged code in acdb17.dll.  Note how the mangled names we located with dumpbin are used as the "EntryPoint" in the [DllImport] attribute.  As is typical when using a standard function call to invoke a method on a target object, a pointer to the target object (in this case, the MLeader) is passed as the first argument in the function call.  The succeeding arguments should match the method signature we found in the ObjectARX documentation.

    Finally, we define the public static methods GetMLeaderScale() and SetMLeaderScale(), which are the methods we use in our code.

    用DllImport封装函数。

    Using the ObjectARX Wrappers

    Our new wrapper is now ready to be used in our code just like any other method.  For example, the snippet of code below will create an MLeader, and if it is not using an Annotative MLeader style, it sets the MLeader scale based on the current CANNOSCALE:

    View Code
    MLeader mleader = new MLeader();
    mleader.SetDatabaseDefaults();
    double scale = 1.0 / (double)Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CANNOSCALEVALUE");
    if (mleader.Annotative != AnnotativeStates.True)
    DatabaseExtensions.SetMLeaderScale(mleader, scale);

    使用封装好的函数的实例。

    This method may be used to access any method in any DLL on your system, as long as that method has been made available to external calls.  It is not the only way to interact with the unmanaged world from the managed world, but it is a relatively simple and effective way to get around those holes in Autodesk's managed API.

    本方法是处理DLL非托管到托管环境的通用方法。





  • 相关阅读:
    TP5 try{}catch{}异常捕获不到 解决办法
    layui2.5 开关在confirm确认了之后在关/开
    JQuery 表单textarea控制字数
    Navicat Premium从远程Mysql数据库复制到本地数据库的方法
    dedecmsV5.7 任意文件上传漏洞修复
    PHP 利用PHPExcel到处数据到Excel;还有导出数据乱码的解决方案。
    Mac Pro 2017款自带php与用brew重装PHP后的地址
    用js传递当前页面的url,丢失了&后面的参数 解决办法
    PHP 超全局变量之$_SERVER
    Linux while和for循环简单分析
  • 原文地址:https://www.cnblogs.com/logitechlike/p/2321425.html
Copyright © 2011-2022 走看看