• 将halcon导出的c++程序打包成dll库



     
    1、从“文件”菜单中,选择“新建”,然后选择“项目…”。 


    2、从“项目类型”窗格中选择“Visual C++”下的“Win32”。 


    3、从“模板”窗格中,选择“Win32 控制台应用程序”。 


    4、为项目选择一个名称,如“MathFuncsDll”,并将其输入“名称”字段。为解决方案选择一个名称,如“DynamicLibrary”,并将其输入“解决方案名称”字段。 


    5、按“确定”启动 Win32 应用程序向导。在“Win32 应用程序向导”对话框的“概述”页中,按“下一步”。 


    6、从“Win32 应用程序向导”中的“应用程序设置”页中,选择“应用程序类型”下的“DLL”(如果可用),或者选择“控制台应用程序”(如果“DLL”不可用)。某些版本的 Visual Studio 不支持使用向导创建 DLL 项目。您可以稍后对此进行更改,以将项目编译为 DLL。 


    7、从“Win32 应用程序向导”的“应用程序设置”页中,选择“附加选项”下的“空项目”。 
    如果你选择的是VC6.0那么你选择选择MFC AppWizdra(DLL)直接就可以生成 
    C#调用C++的Dll文件添加[DllImport("CSharpInvokeCPP.CPPDemo.dll")]就可以如果还不清楚可以参考下面

    背景 

         在项目过程中,有时候你需要调用非C#编写的DLL文件,尤其在使用一些第三方通讯组件的时候,通过C#来开发应用软件时,就需要利用DllImport特性进行方法调用。本篇文章将引导你快速理解这个调用的过程。

    步骤

    1. 创建一个CSharpInvokeCPP的解决方案:

    image

    2. 创建一个C++的动态库项目:

    image

    3. 在应用程序设置中,选择“DLL”,其他按照默认选项:

    image

    最后点击完成,得到如图所示项目:

    image

          我们可以看到这里有一些文件,其中dllmain.cpp作为定义DLL应用程序的入口点,它的作用跟exe文件有个main或者WinMain入口函数是一样的,它就是作为DLL的一个入口函数,实际上它是个可选的文件。它是在静态链接时或动态链接时调用LoadLibrary和FreeLibrary时都会被调用。详细内容可以参考(http://blog.csdn.net/benkaoya/archive/2008/06/02/2504781.aspx)。

    4. 现在我们打开CSharpInvokeCPP.CPPDemo.cpp文件:

    现在我们加入以下内容:

    1 // CSharpInvokeCPP.CPPDemo.cpp : 定义 DLL 应用程序的导出函数。
    2  //
    3  
    4 #include "stdafx.h"
    5
    6  extern"C" __declspec(dllexport) int Add(int x, int y)
    7 {
    8 return x + y;
    9 }
    10  extern"C" __declspec(dllexport) int Sub(int x, int y)
    11 {
    12 return x - y;
    13 }
    14  extern"C" __declspec(dllexport) int Multiply(int x, int y)
    15 {
    16 return x * y;
    17 }
    18  extern"C" __declspec(dllexport) int Divide(int x, int y)
    19 {
    20 return x / y;
    21 }


          extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。而被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。

          __declspec(dllexport)的目的是为了将对应的函数放入到DLL动态库中。

          extern "C" __declspec(dllexport)加起来的目的是为了使用DllImport调用非托管C++的DLL文件。因为使用DllImport只能调用由C语言函数做成的DLL。

    5. 编译项目程序,最后在Debug目录生成CSharpInvokeCPP.CPPDemo.dll和CSharpInvokeCPP.CPPDemo.lib

    image

    我们用反编译工具PE Explorer查看下该DLL里面的方法:

    image

    可以发现对外的公共函数上包含这四种“加减乘除”方法。

    6. 现在来演示下如何利用C#项目来调用非托管C++的DLL,首先创建C#控制台应用程序:

    image

    7. 在CSharpInvokeCSharp.CSharpDemo项目上新建一个CPPDLL类,编写以下代码:

    1 publicclass CPPDLL
    2 {
    3 [DllImport("CSharpInvokeCPP.CPPDemo.dll")]
    4 publicstaticexternint Add(int x, int y);
    5
    6 [DllImport("CSharpInvokeCPP.CPPDemo.dll")]
    7 publicstaticexternint Sub(int x, int y);
    8
    9 [DllImport("CSharpInvokeCPP.CPPDemo.dll")]
    10 publicstaticexternint Multiply(int x, int y);
    11
    12 [DllImport("CSharpInvokeCPP.CPPDemo.dll")]
    13 publicstaticexternint Divide(int x, int y);
    14 }


    DllImport作为C#中对C++的DLL类的导入入口特征,并通过static extern对extern “C”进行对应。

    8. 另外,记得把CPPDemo中生成的DLL文件拷贝到CSharpDemo的bin目录下,你也可以通过设置【项目属性】->【配置属性】->【常规】中的输出目录:

    image

    这样编译项目后,生成的文件就自动输出到CSharpDemo中了。

    9. 然后在Main入口编写测试代码:

    1 staticvoid Main(string[] args)
    2 {
    3 int result = CPPDLL.Add(10, 20);
    4 Console.WriteLine("10 + 20 = {0}", result);
    5
    6 result = CPPDLL.Sub(30, 12);
    7 Console.WriteLine("30 - 12 = {0}", result);
    8
    9 result = CPPDLL.Multiply(5, 4);
    10 Console.WriteLine("5 * 4 = {0}", result);
    11
    12 result = CPPDLL.Divide(30, 5);
    13 Console.WriteLine("30 / 5 = {0}", result);
    14
    15 Console.ReadLine();
    16 }


    运行结果:

    image

    方法得到调用。 

    10. 以上的方法只能通过静态方法对于C++中的函数进行调用。那么怎样通过静态方法去调用C++中一个类对象中的方法呢?现在我在CPPDemo项目中添加一个头文件userinfo.h: 

    1 class UserInfo {
    2  private:
    3 char* m_Name;
    4 int m_Age;
    5  public:
    6 UserInfo(char* name, int age)
    7 {
    8 m_Name = name;
    9 m_Age = age;
    10 }
    11 virtual~UserInfo(){ }
    12 int GetAge() { return m_Age; }
    13 char* GetName() { return m_Name; }
    14 };


    在CSharpInvokeCPP.CPPDemo.cpp中,添加一些代码:

    1#include "malloc.h"
    2#include "userinfo.h"
    3
    4typedef struct {
    5char name[32];
    6int age;
    7} User;
    8
    9UserInfo* userInfo;
    10
    11extern"C" __declspec(dllexport) User* Create(char* name, int age)
    12{
    13 User* user = (User*)malloc(sizeof(User));
    14
    15 userInfo =new UserInfo(name, age);
    16 strcpy(user->name, userInfo->GetName());
    17 user->age = userInfo->GetAge();
    18
    19return user;
    20}

    这里声明一个结构,包括name和age,这个结构是用于和C#方面的结构作个映射。

    注意:代码中的User*是个指针,返回也是一个对象指针,这样做为了防止方法作用域结束后的局部变量的释放。

    strcpy是个复制char数组的函数。

    11. 在CSharpDemo项目中CPPDLL类中补充代码:

    1 [DllImport("CSharpInvokeCPP.CPPDemo.dll")]
    2  publicstaticextern IntPtr Create(string name, int age);
    3
    4 [StructLayout(LayoutKind.Sequential)]
    5  publicstruct User
    6 {
    7 [MarshalAs(UnmanagedType.ByValTStr, SizeConst =32)]
    8 publicstring Name;
    9
    10 publicint Age;
    11 }


    其中这里的结构User就和C++中的User对应。

    12. 在Program.cs中补充代码:

    1 IntPtr ptr = CPPDLL.Create("李平", 27);
    2  <strong><font color="#ff0000">CPPDLL.User user = (CPPDLL.User)Marshal.PtrToStructure(ptr, typeof(CPPDLL.User));</font></strong>
    3 Console.WriteLine("Name: {0}, Age: {1}", user.Name, user.Age);

    注意:红色字体部分,这里结构指针首先转换成IntPtr句柄,然后通过Marshal.PtrToStructrue转换成你所需要的结构。

    运行结果:

    image 

  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/aiyanyan/p/3711404.html
Copyright © 2020-2023  润新知