原文地址:http://5aser.com/forum.php?mod=viewthread&tid=112

写下这个标题的时候,这也许是老生常谈了,遗憾的是本人接触较晚,新人咋到总想尽点微薄之力,而目前影响最深的就属这个了,所以高手莫笑望多多指正,还没有接触的人能指引一下倍感欣慰。
本文环境
vs2010 flashbuilder4.6

1.制作ane文件
第一步.新建一个库项目ExtendingLib 添加新类

package org.leeyou
{import flash.external.ExtensionContext;public class ExtendingFactroy{public static function create():ExtensionContext{return ExtensionContext.createExtensionContext("org.leeyou.Extending", "");}}
}

编译此库 生成swc文件 使用winrar之类的提取 library.swf
第二步.新建extension.xml文件

<extension xmlns="http://ns.adobe.com/air/extension/2.5"><id>org.leeyou.Extending</id><versionNumber>1.0.0</versionNumber><platforms><platform name="Windows-x86"><applicationDeployment><nativeLibrary>Extending.dll</nativeLibrary><!-- dll文件名 --><initializer>Initialize</initializer>        <!-- 初始化函数名 当调用ExtensionContext.createExtensionContext时会回调此函数 --><finalizer>Finalize</finalizer>                <!-- 当改dll卸载时回调的函数 --></applicationDeployment></platform></platforms>
</extension>

第三步.制作Extending.dll
        vs2010新建win32库项目Extending, 引用FlashRuntimeExtensions.h文件和连接该库, 在flex sdk下可以找到这些h文件和lib文件
        编译一个dll文件 此dll有两个导出函数Initialize和Finalize其格式是固定的,函数名字是根据extension.xml中配置文件来的

__declspec(dllexport) void Initialize(void** extData, FREContextInitializer* ctxInitializer, FREContextFinalizer* ctxFinalizer);
__declspec(dllexport) void Finalize(void** extData);

生成一个p12文件 + library.swf + Extending.dll + extension.xml 使用工具adt.bat生成 ane文件 命令如下

"{Your flex sdk path}\bin\adt.bat" -package -storetype pkcs12 -keystore x.p12 -storepass q -target ane ExtendingLib.ane

2.使用ane文件
在app中项目属性 (flex 构建路径)->(本机扩展)->添加此ane, (flex 构建打包)->(本机扩展)->勾选此ane
extension.xml -swc ExtendingLib.swc -platform Windows-x86 library.swf Extending.dll
至此 一个本机扩展啰啰嗦嗦的做完了,但故事还没有完

在windows中加载一个dll并调用其函数两个api

HMODULE module= LoadLibrary("Extending.dll"); //加载Extending.dll
PVOID proc = GetProcAddress(module, "Initialize"); //在此module中找到Initialize的地址,即函数指针
call proc;//调用此函数

ExtensionContext.createExtensionContext正是做的这件事.
既然如此为什么还要制作ane文件?我也不知道,我只是栽过一个跟头即ExtensionContext.createExtensionContext必须在ane文件中调用否则异常之,剩下的不想揣摩别人的心思,只能认为傻逼设计师折磨苦逼程序员。

1.在本机扩展中设置公开的函数
导出函数Initialize

void Initialize(void** extData, FREContextInitializer* ctxInitializer, FREContextFinalizer* ctxFinalizer)
{//extData 要是设置了值将在OnContextInitial中现身*ctxInitializer = &OnContextInitial;//初始化调用的函数*ctxFinalizer = &OnContextFinalize;//释放调用的函数即ExtensionContext.dispose时被调用Alert("Initialize");//调用完此函数马上调用OnContextInitial函数
}
//这里初始化了对as公开的函数表
//extData 是Initialize中设置的值
//ctxType 是在ExtensionContext.createExtensionContext中的第二个参数
//ctx 是flash它玩的
void OnContextInitial(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctions, const FRENamedFunction** functions)
{*numFunctions = 1;                                FRENamedFunction* func = new FRENamedFunction[1]; //表示对as只公开了一个函数func[0].name = (const uint8_t*) "ShowMessageBox"; //函数名字是ShowMessageBoxfunc[0].functionData = NULL;                        //这个任何值,留给自己玩的 即调用ShowMessageBox函数是会再次传过来func[0].function = &ShowMessageBox;                //指向一个函数地址
}
void OnContextFinalize(FREContext ctx)
{
}
FREObject ShowMessageBox(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])//
{FREObject result;uint32_t len = 0;const uint8_t* text = NULL;const uint8_t* caption = NULL;uint32_t type = 0;FREGetObjectAsUTF8(argv[0], &len, &text);//获取第一个参数FREGetObjectAsUTF8(argv[1], &len, &caption);//获取第二个参数FREGetObjectAsUint32(argv[2], &type);//获取第三个参数int ret = MessageBox(NULL, (LPCTSTR)text, (LPCTSTR)caption, type);        FRENewObjectFromInt32(ret, &result);        return result;
}

至此为as提供了一个函数 可以如下调用

context.call("ShowMessageBox", "Hi.", "Extending", 1);

2.本机扩展调用AS函数

如在as中调用时如下:
var o:Object = {};
o.onRunning = function(count:int):void
{trace(count);
};
context.call("ShowMessageBox", "Hi.", "Extending", 1, o);
那么在C++端:
FREObject ShowMessageBox(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])//
{FREObject result;.....FREObject parameters[3];FRENewObjectFromInt32(12, ¶meters[0]);FREResult ret = FRECallObjectMethod(argv[3], (const uint8_t*)"onRunning", 1,  ¶meters[0], ¶meters[1], ¶meters[2]);//至此会在as端输出12.....int ret = MessageBox(NULL, (LPCTSTR)text, (LPCTSTR)caption, type);        FRENewObjectFromInt32(ret, &result);        return result;
}

这里有两个问题需要注意
a.变量的有效期
        在c++端argv此数组在堆栈中。出了这个函数 这个数组里的值是无效的,尽管在as端var o:Object = {};此o永远有效.
        何为堆栈:
        如同一个盒子
        在调用一个函数时先将改函数的上下文(参数,函数内部声明的变量)装入这个盒子 然后再执行这个函数,在执行的过程中从这个盒子拿到想要的上下文.
        当函数调用结束时 把盒子里装入的此上下文清除掉.
        如此 反反复复 进进出出公用这这个盒子
        所以 我们编写的代码潮起又潮落,澎湃汹涌何等壮观啊
        盒子的大小是固定的,这也是为什么在无限递归中有溢出之异常.
        如下:
        function a():void
        {
                var b:int = 0;
                trace(b);//这才有效
        }
        trace(b);这是无效的 因为在当前堆栈中没有b这个变量 只有执行函数a时b才有效
        如想全局的保存一个变量可以使用ExtensionContext.actionScriptData 属性 
        在c++端
        FREObject signalObj = NULL;
        FREGetContextActionScriptData(context, &signalObj);
        获取保存的值.

b.线程同步
        如果在c++端开启的新的线程上下文中调用as端函数 将失败。
        as执行的称之为主线程 运行代码如下:
        while(true)
        {
                .....
                这里 我们在一个很深调用层次中可怜巴巴的写点小破代码
                ....
        }
        而如果在新的线程上下文中调用as函数 则此as函数将运行在上面的while之外,自然失败,原因有二:
                一.每个线程有独立的堆栈,跳出while之外上什么地方去找正确的堆栈,找平衡。
                二.这...倒插一脚,为世人所不齿,自然失败。
        如想同步 在c++端使用
         FREDispatchStatusEventAsync函数
        而在as端使用
         context.addEventListener(StatusEvent.STATUS, onContextStatus);
        可喜可贺的是, 当收到STATUS时,我们的代码又运行在while之中了,遗憾的是这不是同步的
        即FREDispatchStatusEventAsync函数不会等到onContextStatus执行完之后返回,而是立即返回.

至此 本文全部完毕,附上一例.示例中没有做编码转化,在c++端用的是多字节(GB2312)而在flash端使用的是utf-8.

(该示例没能打开,链接附上:http://www.leeyou.net/mblog/display/assets/data/actionscript/extending.zip)

[AIR应用] Air ANE扩展 for windows相关推荐

  1. Adobe AIR教程:ANE面向IAP的测试和开发

    http://mobile.51cto.com/others-302254.htm 本文的内容如下: 在Native扩展中使用StoreKit框架 ActionScript扩展 ANE-IAP开发实例 ...

  2. 开发腾讯移动游戏平台SDK ios版Ane扩展 总结

    本文记录了在开发 腾讯移动游戏平台SDK(MSDK) ios版Ane扩展 过程中所遇到的问题 文中非常多问题都是基础的问题.对object c和xcode配置了解不深入导致的.(没办法,开发ane的程 ...

  3. 多线程、方便扩展的Windows服务程序

    多线程.方便扩展的Windows服务程序 吴剑 2012-06-02 原创文章,转载必需注明出处:http://www.cnblogs.com/wu-jian/ 前言 在项目应用中经常会碰到定时调度的 ...

  4. WSSv3 Technical Articles_使用Visual Studio 2005扩展创建Windows SharePoint Services 3.0 Web Part...

    WSSv3 Technical Articles_使用Visual Studio 2005扩展创建Windows SharePoint Services 3.0 Web Part 摘要:学习使用Mic ...

  5. ipad扩展为Windows的第二屏幕【免费无线版】

    本文参考:Ipad扩展为Windows的第二屏幕 有时候想用ipad作为Windows电脑的第二屏幕,那么我们可以通过spacedesk软件进行无线扩展. 1.在电脑和ipad上分别下载spacede ...

  6. air macbook 风扇响_MacBook装Windows 7后温度过高/风扇过响的解决办法

    很多Macbook都会装双系统,几乎重来不用MacOS,发现Windows 7下,高散热的问题.开机几乎在55°以上.平时打开网页还有聊聊QQ,看看股票软件还好.有的时候看1080P,或者条件智能选股 ...

  7. MacBook Air 13.3系统恢复及Windows 10安装心得

    买了MacBook Air 13.3给媳妇办公用,怕她使用Mac Os不方便,索性通过USB光驱全盘格式化后安装了Windows 10,系统安装完毕后方便风扇声音异常响,比较郁闷,摸索了一整天,整理度 ...

  8. 计算机编程可以用air,Adobe AIR是什么软件?Adobe AIR有什么用?

    谈起Adobe AIR软件,我想很多人会对其感到陌生,甚至不知道它是干什么用的,那么Adobe AIR是什么软件?Adobe AIR有什么用呢?想了解这个软件的朋友不妨看看小编整理的以下文章,有详细介 ...

  9. redis3.2.1php扩展,php7.2.1+redis3.2.1 安装redis扩展(windows系统)

    前提:已成功安装PHP环境和Redis服务 下面进入正题: 第一步,下载redis驱动扩展文件,注意:需要根据上面信息下载对应版本 https://windows.php.net/downloads/ ...

最新文章

  1. 【统计学习】多元统计分析
  2. java hashmap object_Java中的大量Object(使用HashMap)
  3. 记一则js替换字符串的问题
  4. 计算机视觉模型、学习和推理
  5. python入门需要有什么基础?
  6. Elasticsearch SQL插件
  7. SqlServer解析XML,解析JSON数据格式
  8. hdu1695 容斥原理 莫比乌斯反演
  9. mysql约束与索引的区别
  10. 网页视频之H5+Mse
  11. Fisker大师用ZBrush制作兽人萨尔全过程
  12. 系统分析师学习笔记(八)
  13. 光波传输的角谱理论【理论,实例及matlab代码】
  14. 程序员的自我修养有哪些途径
  15. 火狐浏览器怎么录制屏幕_轻松获取Firefox中的屏幕截图
  16. 2023年的深度学习入门指南(1) - 从chatgpt入手
  17. 微信小游戏|unity搭建3D篮球小游戏场景
  18. 高等院校毕业生登记表计算机水平怎么填,关于《高等学校毕业生登记表》填写详细说明...
  19. 年份必须是4位数 C语言,输入年份(四位数),判断是否是闰年 C语言编程
  20. 安势信息入选 SegmentFault思否「2022 中国新锐技术先锋企业」

热门文章

  1. js-屏蔽鼠标和键盘相关事件
  2. Docker系列之入门
  3. CF555E Case of Computer Network
  4. Ag (the_silver_searcher) 安装使用
  5. Leaflet结合wms和wfs实现点击选中要素
  6. 货车刹车失灵坠入百米深谷车成碎片乘客幸存
  7. THIS的几种基本情况和练习题
  8. 27,verilog中整数运算的位宽和符号规则
  9. 过亿付费流量的分餐仪式:体育直播打起“三国杀”
  10. oracle 中( )是什么意思,oracle 中的(+) 是什么意思?