在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
上一篇《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 // 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> // 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_SET* stru ) extern "C" __declspec(dllexport) float* WINAPI add3() // 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)] //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(); IntPtr d = add3();
[StructLayout(LayoutKind.Sequential)] ----------------------------------------------------------------------------------------- .net调用C DLL 编写C程序如下: #include "stdio.h"
保存,取名为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) ----------------------------------------------------------------------------------------- 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); }
|
请发表评论