6

我正在尝试使用用 C++ 编写的 DLL,但我的应用程序是用 C# 编写的

DLL 来自另一家公司,但他们为他们的软件提供了 SDK。

他们给出了一个如何在 C++ 中加载他们的 DLL 的示例,但我需要将其调整为 C#。

以下是他们如何在 C++ 中执行此操作的说明

MarkEzd.dll 文件是动态链接库。

MarkEzdDll.h 是 MarkEzd.dll 中导出函数的头文件

MarkEzd.dll 的调用方式是显式链接。开发者需要通过调用 Windows API 函数来加载和释放 MarkEzd.dll。

步骤如下。

  1. 调用Windows的API函数LoadLibrary()动态加载DLL;

  2. 调用Windows的API函数GetProcAddrress()获取DLL中函数的指针,并利用函数指针完成工作;

  3. 不使用 DLL 或程序结束时,调用 Windows 的 API 函数 FreeLibrary() 释放库。

以下是他们提供的示例。

步骤 2. 调用 markezd.dll 的程序软件。a) 第一步:动态加载 MarkEzd.dll

HINSTANCE hEzdDLL = LoadLibrary(_T("MarkEzd.dll"));

b) 第二步:获取要调用的函数的指针

lmc1_Initial=(LMC1_INITIAL)GetProcAddress(hEzdDLL, _T("lmc1_Initial"));
lmc1_Close=(LMC1_CLOSE)GetProcAddress(hEzdDLL, _T("lmc1_Close"));
lmc1_LoadEzdFile=(LMC1_LOADEZDFILE)GetProcAddress(hEzdDLL,_T("lmc1_LoadEzdFile"));  
lmc1_Mark=(LMC1_MARK)GetProcAddress(hEzdDLL,_T("lmc1_Mark"));

c) 第三步:调用函数

1) 初始化lmc1板: lmc1_Initial().
2) 打开test.ezd: lmc1_LoadEzdFile(_T(“test.ezd”)).
3) 调用lmc1_Mark()进行加工:lmc1_Mark().
4) 关闭lmc1板:lmc1_Close().

d) 第四步,释放markezd.dll:FreeLibrary(hEzdDLL)

下面是命令的描述。

lmc1_Initial
INTENTION:初始化lmc1控制板
定义:int lmc1_Initial(TCHAR* strEzCadPath, BOOL bTestMode, HWND hOwenWnd)
strEzCadPath:ezcad2.exe所在的完整路径
bTestMode 是否处于测试模式
hOwenWnd:有焦点的窗口。它用于检查用户的停止消息。说明:您必须先调用 lmc1¬_Initial,然后再调用程序中的其他函数。
返回值:常见错误码

lmc1_Close 意图
:关闭 lmc1 板
定义:int lmc1_Close();
描述:退出程序时必须调用 lmc1_Close 来关闭 lmc1 板。
返回值:常见错误码

lmc1_LoadEzdFile 意图
:打开指定的ezd文件,清除数据库中的所有对象。
定义:int lmc1_LoadEzdFile(TCHAR* strFileName);
描述:此函数可以打开一个由用户构建的ezd文件作为模板。用户无需设置工艺参数,因为它们将从模板文件中加载。
返回值:常见错误码

lmc1_Mark
INTENTION: 标记数据库中的所有数据
定义: int lmc1_Mark(BOOL bFlyMark);
bFlyMark= TRUE // mark on fly
说明: 使用 lmc1_LoadEzdFile 加载 ezd 文件后调用此函数开始标记。该函数在标记完成之前不会返回。
返回值:常见错误码

他们还解释了如何设置 VS6.0

  1. 安装visual studio时选择“Microsoft Visual C++ 6.0”,点击“Change Option”。
  2. 选择“VC++ MFC 和模板库”并单击“更改选项”。
  3. 选择“MS Foundation Class Libraries”并单击“更改选项”。
  4. 选择如下图选项,点击“确定”。
  5. 打开项目,选择菜单项目->设置。选择“C/C++”,在“预处理器定义”中添加“UNICODE”并删除“MCBS”</li>
  6. 选择“Link”,在Category中选择“Output”,在“Entry-point symbol”中添加“wWinMainCRTStartup”</li>
  7. 将源代码中的所有“char”更改为“TCHAR”。
  8. 将双引号“…”包含的所有字符串更改为_T(“…”)
  9. 再次编译并链接项目。

大多数函数返回一个整数代码 0 表示成功。

这是正确的吗?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;


namespace Start_Mark
{
    public partial class Form1 : Form
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);

        [DllImport("MarkEzd.dll")]
        [return: MarshalAs(UnmanagedType.I2)]
        public static extern int lmc1_Initial(string strEzCadPath, bool bTestMode, IntPtr hOwenWnd);

        [DllImport("MarkEzd.dll")]
        [return: MarshalAs(UnmanagedType.I2)]
        public static extern int lmc1_Close();

        [DllImport("MarkEzd.dll")]
        [return: MarshalAs(UnmanagedType.I2)]
        public static extern int lmc1_LoadEzdFile(string strFileName);

        [DllImport("MarkEzd.dll")]
        [return: MarshalAs(UnmanagedType.I2)]
        public static extern int lmc1_Mark(bool bFlyMark);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            IntPtr hEzdDLL = LoadLibrary("MarkEzd.dll");
            IntPtr iplmc1_Initial = GetProcAddress(hEzdDLL, "lmc1_Initial");
            IntPtr iplmc1_Close = GetProcAddress(hEzdDLL, "lmc1_Close");
            IntPtr iplmc1_LoadEzdFile = GetProcAddress(hEzdDLL, "lmc1_LoadEzdFile");
            IntPtr iplmc1_Mark = GetProcAddress(hEzdDLL, "lmc1_Mark");
            int intlmc1_Initial=lmc1_Initial("c:\temp", false, hEzdDLL);
            if (intlmc1_Initial > 0)
            {
                return;
            }
            int intlmc1_LoadEzdFile = lmc1_LoadEzdFile("c:\temp\test.ezd");
            if (intlmc1_LoadEzdFile > 0)
            {
                return;
            }
            int intlmc1_Mark = lmc1_Mark(true);
            if (intlmc1_Mark > 0)
            {
                return;
            }
            int intlmc1_Close = lmc1_Close();
            if (intlmc1_Close > 0)
            {
                return;
            }
            FreeLibrary(hEzdDLL);
        }
    }
}
4

2 回答 2

5

正确的语法如下。

using System;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Company.Group
{
    public class FuncList
    {
        [DllImport("MarkEzd.dll", EntryPoint = "lmc1_Initial2", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
        public static extern int Initialize(string PathName, bool TestMode);
    }
}
于 2014-11-07T15:09:29.500 回答
2

使用 P-Invoke 调用本机 DLL。您可能必须编组一些数据类型才能使其工作。

http://msdn.microsoft.com/en-us/library/aa288468.aspx

于 2013-03-29T17:07:46.087 回答