• 在windows phone Mango中使用原生代码开发程序


        本文不讨论创建可执行的exe程序,主要想说明怎么在silverlight程序里面调用由原生代码所编写的DLL(C++ / ARM).

        原生代码可以调用更多的API,但是这并不是说你就能随意获得那些你没有权限的资源,比如,你可以使用CopyFile这个API,但是如果你试图把文件Copy到\Windows文件夹,就会得到一个0x4ec的错误代码,系统会禁止你这样做.所以,你的程序也只能在沙箱的环境下运行.

        本文中所涉及的知识包含 C++,COM交互,Windows phone 程序设计.希望你在开发你的程序前能保证熟悉这些技术.因为原生代码还不能调试,所以你只能使用返回错误信息的方式来确保你的程序能正确运行.

        需要注意的是: 如果你有些任务需要执行很长时间,它们在调试的时候能很好的运行,但是在实际运行的时候,你最好采用一个线程来做这些事情.因为在非调试状态下检测程序会检测你的程序,一但你的程序锁定超过10秒,那么系统会自动退出这个程序.

       有人建议原生代码所写的DLL需要签名,其实这并不是必须的.在Mango设备里面可以使用未签名的库.

       讨论一下互操作锁.详细讨论可以参见这个贴子.互操作锁在WP7.5里面出现.最直观的表现就是你的程序如果使用了ID_CAP_INTEROPSERVICES,那么所使用的设备必须得解锁.

       下面就是一个详细的操作步骤:

     PS: 所需要的软件请点击名称下载

       1. 安装 Visual Studio 2008 及 最新的补丁包,确保安装 C++.

       2. 安装 Windows Modile 6 Professional SDK Resfresh.

       3. 安装 Visual Studio 2010 和 最新的补丁包.

       4. 安装 Windows Phone SDK 7.1

       5. 下载 Microsoft.Phone.InteropServices.zip. 下载解压后要确定文件是非锁定状态,解锁可以按以下操作,文件是点击右键,选择属性,点击解锁.

       6. 把Microsoft.Phone.InteropServices.dll放到  C:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone71 ,如果是64位系统就放到 C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone71.

       7. 打开 Visual Studio 2010 的命令行工具,转到Microsoft.Phone.InteropServices.dll放置的地方,输入以下代码,请确定注册成功.否则引用这个DLL时会报没有引用命名.

    SN -Vr Microsoft.Phone.InteropServices.dll
    

     8. 在DLL的目录下有一个RedistList文件夹,里面有一FrameworkList.xml,加下面代码

    <File AssemblyName="Microsoft.Phone.InteropServices" Version="7.0.0.0" Culture="neutral" ProcessorArchitecture="MSIL" InGac="false" />

     9.  安装 zune

       10. 打开 VS2008,创建新项目.

       11. 选择 Visual C++ / Smart Device / ATL Smart Device 项目,不能选择MFC.

       12. 点击下一步

       13. 取消 Pocket PC 2003,加入 Windows Mobile 6 Pro SDK,点击下一步

       14. 点击完成

       15. 编译设置为 Release.

       16. 在工程属性 / 属性配置 / C/C++ / 预处理 / 预处理定义里面加入 

    _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA
    

     17. 在工程里面加入一个新类 , 选择 "Simple ATL object"

       18. 对话框内 "Short name"是 Com类的名字,其他可以保持默认,点击完成.

       19. 文件添加就完成了.包含这些文件 : 头文件(.h) ,代码文件 (.cpp) , Com定义文件(.idl), Com类的头文件(.h),Com类的代码文件(.cpp).

       20. 把Com类的基类改成 IUnknown.

       21. 在Com类的头文件中,删除下面这一句

    COM_INTERFACE_ENTRY(IDispatch)
    

     22. 在IDL文件中,把IDispatch改成IUnknown.

       23. 现在可以向你的Com类加入方法了.所有方法都必须以HRESULT为返回值.这个值用来判断函数是否执行成成功.成功可以返回 S_OK,如果有错误代码,则把错误代码与0x80070000进行逻辑或的结果做为返回值.如果你想返回一个变量,你需要在IDL文件里面声明他.参数以COM为边界,参见这里这里查看COM支持的参数类型.

       24. 在COM类中加入如下代码:

     1 STDMETHODIMP CNative::TestMethod1()
    2 {
    3 BOOL result = ::CopyFile(L"\\Windows\\0000_System.Windows.xaml", L"\\Windows\\Test.xaml", TRUE); //这里会抛出一个异常
    4 if (result)
    5 return S_OK;
    6 else
    7 return 0x80070000 | ::GetLastError();
    8 }
    9 STDMETHODIMP CNative::TestMethod2(BSTR InputString, BSTR* OutputString)
    10 {
    11 size_t size = 1000; // in chars
    12 TCHAR* msg = new TCHAR[size];
    13 wcscpy_s(msg, size, L"\0");
    14
    15 LPWSTR value = new WCHAR[20];
    16
    17 _itow((int)wcslen(InputString), value, 10);
    18 wcscat_s(msg, size, L"Length of string is: ");
    19 wcscat_s(msg, size, value);
    20
    21 *OutputString = SysAllocString(msg);
    22
    23 delete[] msg;
    24 delete[] value;
    25
    26 return S_OK;
    27 }

     25. Com类的头文件中加入下面代码,放在END_COM_MAP()后面

    1 STDMETHOD(TestMethod1)();
    2 STDMETHOD(TestMethod2)(BSTR InputString, BSTR* OutputString);

     26. 在IDL文件里面加如如下代码,关于参数定义,可以查看 点击我吧

    1 HRESULT TestMethod1();
    2 HRESULT TestMethod2(BSTR InputString, BSTR* OutputString);

     27. 记下IDL文件里面的接口GUID(uuid标识),类标识GUID.

       28. 在VS2010里面创建一个新的WP工程.

       29. VS2008里面编译生成DLL,然后把DLL拷贝到WP工程目录下.

       30. 在WP工程下创建WPInteropManifest.xml文件,内容为

    1 <?xml version="1.0" encoding="UTF-8"?>
    2 <Interop>
    3 </Interop>

      31. 更改WPInteropManifest.xml文件的编译规则为"Content","Copy if newer".

      32. 更改COM输出的DLL编译规则为"Content","Copy if newer"

      33. WP工程添加引用"Microsoft.Phone.InteropServices"

      34. 打开WMAppManifest.xml文件,添加

    <Capability Name="ID_CAP_INTEROPSERVICES" />

      35. 添加一个代码文件 输入以下内容:

     1 using System.Runtime.InteropServices;
    2
    3 [ComImport, ClassInterface(ClassInterfaceType.None), Guid("YOUR-COCLASS-GUID-GOES-HERE")]
    4 public class CNative
    5 {
    6 }
    7
    8 [ComImport, Guid("YOUR-INTERFACE-GUID-GOES-HERE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    9 public interface INative
    10 {
    11 void TestMethod1();
    12 [return : MarshalAs(UnmanagedType.BStr)]
    13 string TestMethod2([MarshalAs(UnmanagedType.BStr)] string InputString);
    14 }

       36.创建一个测试代码文件,输入以入内容

     1 uint retval = Microsoft.Phone.InteropServices.ComBridge.RegisterComDll("Your Com DLL.dll", new Guid("YOUR-COCLASS-GUID-GOES-HERE"));
    2 INative MyNativeCodeInstance = (INative)new CNative();
    3 string result1 = "OK";
    4 try
    5 {
    6 MyNativeCodeInstance.TestMethod1(); //这里抛出一个异常
    7 }
    8 catch (Exception ex)
    9 {
    10 result1 = ex.Message;
    11 }
    12 string result2 = MyNativeCodeInstance.TestMethod2("Hello, Mango!");
    13 MessageBox.Show(result1 + Environment.NewLine + result2);

       37. 运行程序,测试代码.

       38. 注意,当使用高级功能时.我们需要Marshal-class,比如操作内存等.此时需要使用Microsoft.Phone.InteropServices内的Marshal类,如果使用System.Runtime.InteropServices命名空间下的此类,会抛出一个MethodAccessException异常.

       关于简单的调用方法就说到这里.希望大家都能搞出更好的自制程序.如果翻译或者描述有不准确的地方,希望大家指正,谢谢!!

    原贴地址: http://forum.xda-developers.com/showthread.php?t=1299134

  • 相关阅读:
    轻量级锁和偏向锁等
    桥接模式
    适配器模式
    建造者模式
    2-工厂模式
    Swift
    给视图添加点击波纹效果swift5
    Xcode 支持真机版本路径
    22个常用开源库(most swift)
    Github上关于iOS的各种开源项目集合
  • 原文地址:https://www.cnblogs.com/thilong/p/2367556.html
Copyright © 2020-2023  润新知