zoukankan      html  css  js  c++  java
  • Silverlight5通过P/Invoke调用自定义C/C++ DLL(Lua)

       上一篇《Silverlight5通过P/Invoke调用系统win32的三个示例》展示了silverlight5通过P/Invoke调用系统win32的三个示例,本篇给出自定义win32 dll及其在Silverlight5中调用的代码。

      注1:为了确保silverilght5在浏览器或桌面上成功调用win32 DLL,必须在项目属性中勾选相应的权限:

        勾选Enable running application out of the browser及其Require elevated trust when running in-browser

        勾选Require elevated trust when running in-browser

      注2:win32 dll文件编译后放在\windows\system32或\windows\system目录下,win7 x64的系统放在后者。

      注3:winform/wpf中调用类似

    .h

    // The following ifdef block is the standard way of creating macros which make exporting 
    // from a DLL simpler. All files within this DLL are compiled with the MYDLL_EXPORTS
    // symbol defined on the command line. This symbol should not be defined on any project
    // that uses this DLL. This way any other project whose source files include this file see 
    // MYDLL_API functions as being imported from a DLL, whereas this DLL sees symbols
    // defined with this macro as being exported.
    #ifdef MYDLL_EXPORTS
    #define MYDLL_API __declspec(dllexport)
    #else
    #define MYDLL_API __declspec(dllimport)
    #endif
    
    struct HHFC_SET 
    {
    ;charUID;
      int     code;
    };
    // This class is exported from the MyDLL.dll
    class MYDLL_API CMyDLL {
    public:
    	CMyDLL(void);
    	// TODO: add your methods here.
    };
    //extern MYDLL_API int nMyDLL;
    extern "C" MYDLL_API int nMyDLL; 
    extern "C" MYDLL_API float fnMyDLL(float x ,float y);// 注意得加上extern  "C",否则无法P/Invoke

    .cpp

    #include "stdafx.h"
    #include "MyDLL.h"
    
    #include <iostream>   
    #include "LuaPlus.h"
    #include "LuaPlusHelper.h"
    #pragma comment(lib,"LuaPlusLib.lib")  
    using namespace LuaPlus;
    using namespace std;
    // This is an example of an exported variable
    MYDLL_API int nMyDLL=0;
    // This is an example of an exported function. 
    MYDLL_API float fnMyDLL(float x ,float y)
    {
        //调用Lua脚本并计算
        string str;
        str.append("function Add(x, y)\n");
        str.append(" return x*y;\n");
        str.append("end\n");
        int iret = state->DoString(str.c_str());// state->DoFile("a.lua");
        LuaFunction Add = state->GetGlobal("Add");
        float myret = Add(x,y);
        return myret;
    } 
    extern "C" __declspec(dllexport)  int WINAPI add()
    {
    	return 101;
    }
    
    extern "C" __declspec(dllexport)  int WINAPI add2(HHFC_SETstru )
    {
    stru->UID="this is a win32 test about struct";
    stru->code=3;
       return 1;
    }
    extern "C" __declspec(dllexport) float* WINAPI add3()
    {
     float* num=(float*)malloc(4);
     num[0]=11.2f;
     num[1]=21.3f;
     num[2]=33.5f;
     num[3]=46.2f;
     return num;
    }
    // This is the constructor of a class that has been exported.
    // see MyDLL.h for the class definition
    CMyDLL::CMyDLL()
    {
    	return;
    }
    

    .xaml

        <Grid x:Name="LayoutRoot" Background="White">
    
            <StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="24,24,0,0">
                <TextBlock Name="textBlock1" Text="add       函数结果:" Height="23" />
                <TextBox Name="textBox1" Width="120" Height="23" />
            </StackPanel>
    
            <StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="24,64,0,0">
                <TextBlock Name="textBlock2" Text="fnMyDLL函数结果:" Height="23"/>
                <TextBox Name="textBox2" VerticalAlignment="Top" Width="120" Height="23"/>
            </StackPanel>
           
    
            <Button Content="Button" Height="32" Margin="120,101,202,0" Name="button1" VerticalAlignment="Top" Width="78" Click="button1_Click" />
        </Grid>
    

    .cs

    public partial class MainPage : UserControl
        {
            [DllImportAttribute("user32.dll", EntryPoint = "MessageBoxW")]
            public static extern int MessageBoxW(int hWnd, [In][MarshalAs(UnmanagedType.LPWStr)] string lpText, [In][MarshalAs(UnmanagedType.LPWStr)] string lpCaption, int uType);
    
            [DllImport("MyDll.dll", EntryPoint = "add", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = false)]
            public static extern int add();
    
            [DllImport("MyDll.dll", EntryPoint = "fnMyDLL", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi, SetLastError = false)]
            public static extern float fnMyDLL(float x,float y);
    
            [DllImport("MyDLL.dll", EntryPoint = "add2", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi, SetLastError = false)]
            public static extern int add2(ref HHFC_SET stru);
    
            [DllImport("MYDLL.dll", EntryPoint = "add3", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi, SetLastError = false)]
           public static extern IntPtr add3();
            //EntryPoint: 指定要调用的 DLL 入口点。默认入口点名称是托管方法的名称 。 
            //CharSet: 控制名称重整和封送 String 参数的方式 (默认是UNICODE) 
            //CallingConvention指示入口点的函数调用约定(默认WINAPI) 
            //SetLastError 指示被调用方在从属性化方法返回之前是否调用 SetLastError Win32 API 函数 (C#中默认false )
    
            public MainPage()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                this.textBox1.Text = add().ToString();
                this.textBox2.Text = fnMyDLL(12,2).ToString();
                MessageBoxW(0, "提交成功", "温馨提示", 0);
    
                HHFC_SET stru = new HHFC_SET(); 
                stru.Uid = "";
                Console.WriteLine(stru.Uid);
                int a = add2(ref stru);
                Console.WriteLine(stru.Uid);
                IntPtr d = add3();
               float[] bytes2 = new float[Marshal.SizeOf(d)];
               Marshal.Copy(d, bytes2, 0, 4);

            }
    }
        [StructLayout(LayoutKind.Sequential)]
        public struct HHFC_SET
        {
            [MarshalAs(UnmanagedType.LPStr)]
            public String Uid;

          [MarshalAs(UnmanagedType.I4)]
            public int code;
        }
     

    -----------------------------------------------------------------------------------------  

    .net调用C DLL 

    编写C程序如下:

    #include "stdio.h"
    __declspec(dllexport) void MyFun() {     printf("this is a dll\n"); }

    保存,取名为My.C

    运行 VS 命令提示,Cl /c  路径/My.c

    运行以后会生成 My.Obj,默认在vs安装文件夹的VC目录下

    再运行 link/dll   路径/My.obj

    在同一个目录会生成My.dll

    在C#中调用:

    将dll复制到bin目录,编写如下C#代码:

    static void Main(string[] args)
    {
       MyFun();
    }
    [DllImport("My.dll")]
    public extern static void MyFun();

    -----------------------------------------------------------------------------------------   

    C#传委托给C的函数指针调用问题

    C代码如下:

    #include "stdio.h"
    __declspec(dllexport) int Call(int (*qq)(int num),char * str)
    {    
        printf(str);
        return qq(123);
    }
    

    多次验证发现在C#中传委托给C中的函数指针,如果委托不带参数则都能成功运行,但是委托一带参数不管是int参数还是string参数或者其他参数,都会报“ 尝试读取或写入受保护的内存。这通常指示其他内存已损坏”的错误,找了一天才找到解决方法,既在C#的委托声明上加[UnmanagedFunctionPointer(CallingConvention.Cdecl)],正确调用如下:

     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate int MyDeg(int num);
        class Program
        {
            static void Main(string[] args)
            {
                
                try
                {
                    MyDeg myd = new MyDeg(FF);
                    Console.WriteLine(Call(myd, "helloworld"));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
    
            }
    
            static int FF(int num)
            {
                Console.WriteLine(num);
                return num + 1;
    
            }
    
            [DllImport("my.dll", EntryPoint = "Call")]
            public extern static int Call(MyDeg mm ,string  str);
        }
    

      

  • 相关阅读:
    spring boot 打包 jar 实现第三方零配置引用
    spring boot 整合log4j2
    linux cat 模糊查询日志命令
    docker深入浅出
    docker容器为啥一定要前台运行
    李诚云原生技术分享
    k8s中对应的stateful有状态服务的讲解
    k8s networkpolicy网络策略详解
    k8s中IngressIp和egressIp的区别
    技术丨小团队微服务落地实践
  • 原文地址:https://www.cnblogs.com/chuncn/p/2314020.html
Copyright © 2011-2022 走看看