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 { ; char * UID; 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_SET* stru ) { 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); } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步