c++与c#的交互
项目基本上是c++写的,现在要移植到wp8上,坑啊,c#不会啊
查了下资料,发现目前来说,c++与c#交互主要有2中方法:
http://stackoverflow.com/questions/14434874/calling-c-sharp-method-from-c-code-in-wp8
http://www.cnblogs.com/zhxilin/archive/2013/03/20/2971331.html
这2中方法都不太熟,但是看着第一种方法简单,所以采取了第一种方法,具体过程如下:
1. 在项目的解决方案下,添加一个新项目,选择 windows phone空动态链接库,我这里输入的工程名为Dll
注意,如果添加windows phone运行时组件也是可以的,二者的区别在于动态链接库字符集默认为ascii
而运行时组件字符集默认为Unicode,这个是个人实验得出的,具体到个人,可能会有不同
如果选择动态链接库,需要做如下设置:
选择,项目->属性
在 c/c++, 常规,使用Windows运行时扩展 选项,选择 是(/ZW);
在 c/c++, 预处理器,预处理器定义 中添加 _WINRT_DLL,这样如果不做,可能会在运行时
遇见Error in the DLL (Exception from HRESULT: 0x800401F9 (CO_E_ERRORINDLL))
的错误
在 c/c++, 代码生成,启动最小重新生成 选项,选择 否(/Gm-), 这里默认为是,
如果设置了使用Windows运行时扩展,而这里不调整,会提示/ZW 与 /Gm- 不兼容
在 连接器,Windows元数据,生成Windows元数据 选项,选择 是(/WINMD), 这里选择生成元数据供
C#调用c++;
2. 在头文件Dll.h中添加代码,如下:
#pragma once
namespace Dll
{
public interface class ICallback
{
public:
virtual void Exec(Platform::String ^Command, Platform::String ^Param);
};
public ref class MYTest sealed
{
public:
MYTest();
void Init();
int AT(int a, int b);
void SetCallback(ICallback ^Callback);
void SetRet(int result);
void show();
};
}
其实这里主要的就是那个interface的类了,ICallback里面的虚函数Exec在C#里面实现,供c++调用
下面的那个MYTest类里面的函数,最主要的是SetCallback,用来获取c#里面的对象
在Dll.cpp中添加方法,代码如下:
#include "pch.h"
#include "TDll.h"
#include <stdio.h>
#include <string.h>
using namespace Dll;
ICallback ^CSCallback = nullptr;
void * handle = nullptr;
int ret;
MYTest::MYTest()
{
ret = -1;
}
void MYTest::Init()
{
}
int MYTest::AT(int a, int b)
{
if (CSCallback != nullptr)
CSCallback->Exec("Hello", "World!");
return a + b;
}
void MYTest::SetCallback(ICallback ^Callback)
{
CSCallback = Callback;
}
void MYTest::SetRet(int result)
{
ret = result;
}
void MYTest::show()
{
char ch[10] = { 0 };
sprintf(ch, "ret:%d\n", ret);
OutputDebugString(ch);
}
其中AT方法是一个调用c#方法的函数,明显得,调用Exec方法,传递2个参数
3. 在wp8工程 中添加如下代码:
//MainPage.xaml.cs:
namespace QRCode
{
private MYTest test = new MYTest();
......
private void Button_Click(object sender, RoutedEventArgs e)
{
count++;
if (count == 1)
{
int ret = test.AT(2, 3);
Debug.WriteLine("main page:" + ret);
}
else
test.show();
}
......
public class CallbackImpl : ICallback
{
public void Exec(String Command, String Param)
{
Debug.WriteLine(Command + Param);
(Application.Current.RootVisual as PhoneApplicationFrame).Navigate(new Uri("/ScanPage.xaml", UriKind.Relative));
}
}
}
CallbackImpl里面的Exec是c++中相应虚函数的实现,这里Exec主要是用来跳转到ScanPage.xaml页面
//ScanPage.xaml.cs:
namespace QRCode
{
private MYTest te = new MYTest();
.....
private void ScanPreviewBuffer()
{
.....
te.SetRet(0);
te.show();
.....
}
}
ScanPage扫描二维码,如果成功,设置c++中的ret作为返回值,返回
注意,如果Dll依赖与其他dll,需要将依赖的dll手动添加到wp8工程当中,
否则,wp8打包时是不会主动将依赖dll打包进xap包的,但编译不会报错,运行时会报错
4. 选择wp8工程,右键,添加,引用,浏览,找到Dll.wind,确定
编译,第一次编译可能会提示wp8工程错误,再次编译就好了,主要是第一次编译找不到.wind
有时候会遇见Access is denied的运行错误,此时,打开wp8工程下Porperties标签,
打开WMAppManifest.xml文件,选择 功能 项,勾选需要的功能
比如这里用到摄像头,所以要勾选ID_CAP_ISV_CAMERA项
其实不麻烦,主要是个人水平问题,感觉就一个字,坑
具体的代码可以在下面的链接中下载
参考:
http://stackoverflow.com/questions/14434874/calling-c-sharp-method-from-c-code-in-wp8
http://blog.webrox.fr/?p=67
http://www.cnblogs.com/zhxilin/archive/2013/03/20/2971331.html
http://hi.baidu.com/huangjianspace/item/e437fb1ee194caf29d778a03
https://social.msdn.microsoft.com/Forums/windowsapps/en-US/3db59292-
8abb-4bfd-a46e-926ad78239f9/wp81-getfoldersasync-access-is-denied-ex
ception-from-hresult-0x80070005-eaccessdenied?forum=wpdevelop