C++ 与C#,FLEX之间的函数调用

一、C#调用C++DLL 的普通函数和回调函数(C/C++内回调函数一般通过传递函数指针来实现,函数指针在C#中对应的就是委托

C++ 代码:

//***********普通函数的导出****************
extern "C" _declspec(dllimport)  int __stdcall Add(int num_one, int num_two);
//***********回调函数的导出*****************
typedef void (*callback_t)(int);
extern "C" _declspec(dllimport)  bool  __stdcall processCallback(callback_t, int param);

C#代码

       public delegate void CallbackDelegate(int a); //声明委托  
        //接口定义
      [DllImport(@"E:\IDATABK\DllTest\Debug\DllTest.dll", EntryPoint = "Add")]
        public static extern int Add(int b, int a);
      [DllImport(@"E:\IDATABK\DllTest\Debug\DllTest.dll", EntryPoint = "_processCallback@8")]  
        public static extern bool processCallback(CallbackDelegate call,int a);
      //调用示例
      public CallbackDelegate myDelegate = new CallbackDelegate(CallbackFunc); 
       int result= Add(1, 2);
       processCallback(myDelegate, 3);

C#回调函数

 public static void CallbackFunc(int a)
 {
      Console.WriteLine("参数1: {0}", a);
  } 

二 、 FLEX 调用C++的函数和回调函数

1、 建立一个C++的DLL ,这里要使用FLEX正对于C++写的一个运行库(FlashRuntimeExtensions.lib,使用方法查看官网文档),可以在FLASH BUILDER 的安装目录里找到

C++的.h 文件

#include "FlashRuntimeExtensions.h"

extern "C"
{
	__declspec(dllexport) void initializer(void** extData, FREContextInitializer* ctxInitializer, FREContextFinalizer* ctxFinalizer);
	__declspec(dllexport) void finalizer(void* extData);
}
C++ DLL 的CPP 文件
// ANETest.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include <process.h>
#include "ANETest.h"


FREContext context;

//转换中文
void utf8_to_ansi(char* src, char* &dest) 
{
	int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, src, strlen(src), NULL, 0);//测试转换
	wchar_t* wszString = new wchar_t[wcsLen + 1];
	::MultiByteToWideChar(CP_UTF8, NULL, src, strlen(src), wszString, wcsLen);  //utf8 转Unicode
	wszString[wcsLen] = '\0';

	int ansiLen = ::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), NULL, 0, NULL, NULL);
	dest = new char[ansiLen + 1];	//unicode版对应的strlen是wcslen
	::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), dest, ansiLen, NULL, NULL);
	dest[ansiLen] = '\0';
	delete [] wszString;
}

//获取Char*长度
int getCharLength(char *chr)
{
	int i = 0;
	while (chr[i] != '\0') {
		i++;
	}
	return i;
}

//拼接两个char*
char *addChar(char *a, char *b)
{
	char* c;
	c = (char*)malloc((getCharLength(a) + getCharLength(b) + 1)*sizeof(char));
	int i,j = 0;
	for (i = 0;a[i] != '\0';i++) {
		c[j] = a[i];
		j++;
	}
	for (i = 0; b[i] != '\0';i++) {
		c[j] = b[i];
		j++;
	}
	c[j] = '\0';

	return c;
}

//sayHello
FREObject sayHello(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
	uint32_t strLen;
	const uint8_t * pName;
	FREGetObjectAsUTF8(argv[0], &strLen, &pName);
	char* name;
	utf8_to_ansi((char*)pName, name);
	char* hi = "Hello, ";
	char *ret;
	ret = addChar(hi, name);

	FREObject objectByteArray = argv[1];
	FREByteArray byteArray;
	FREObject length;
	FRENewObjectFromUint32(getCharLength(ret), &length);
	FRESetObjectProperty(objectByteArray, (const uint8_t*) "length", length, NULL);
	FREAcquireByteArray(objectByteArray, &byteArray);
	memcpy(byteArray.bytes, ret, getCharLength(ret));
	FREReleaseByteArray(objectByteArray);
	return NULL;
}
/***********定义回调函数*****************/
typedef void (*callback_t)();
bool processCallback(callback_t p)
{
	p();
	return true;
}
/************回调函数的使用*****************/
FREObject callBackHello(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{

	FREObject objectByteArray = argv[0];
	const uint8_t * pName;
	uint32_t strLen;
	FREGetObjectAsUTF8(argv[1], &strLen, &pName);
	FREObject  re;
	FREResult es=FRECallObjectMethod(objectByteArray,pName,0,NULL,&re,NULL);
	FREObject rest;
	FRENewObjectFromInt32((int32_t)es,&rest);
	return rest;
}
void __cdecl eventTestThread(void* param) {
	_sleep(1000);
	const uint8_t* msg1 = (const uint8_t*)"Hello World";
    const uint8_t* msg2 = (const uint8_t*)"Message";
    FREDispatchStatusEventAsync(context,msg1,msg2);
	context = NULL;
}

FREObject eventTest(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
	context = ctx;
	_beginthread(eventTestThread, 0, NULL);
	return NULL;
}

//方法信息
void contextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctions, const FRENamedFunction** functions)
{
	*numFunctions = 3;

	FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * (*numFunctions));
	/********对于每一个方法的调用都要在此说明**********/
	func[0].name = (const uint8_t*) "sayHello";
	func[0].functionData = NULL;
	func[0].function = &sayHello;

	func[1].name = (const uint8_t*) "eventTest";
	func[1].functionData = NULL;
	func[1].function = &eventTest;
	func[2].name = (const uint8_t*) "callBackHello";
	func[2].functionData = NULL;
	func[2].function = &callBackHello;

	*functions = func;
}

void contextFinalizer(FREContext ctx)
{
	return;
}

extern "C"
{
	void initializer(void** extData, FREContextInitializer* ctxInitializer, FREContextFinalizer* ctxFinalizer)
	{
		*ctxInitializer = &contextInitializer;
		*ctxFinalizer = &contextFinalizer;
	}

	void finalizer(void* extData)
	{
		return;
	}
}

FLEX 端的操作

在FLEX中添加一个AIR 的桌面项目,将C++编译的DLL(CTest.dll) 添加到将其拷贝到Air工程extensions\src\windows目录下,打开

打开extensions.xml

<extension xmlns="http://ns.adobe.com/air/extension/3.1">
	<id>com.bankcomm.test.CTestDll</id>
	<versionNumber>1.0.0</versionNumber>
	<platforms>
		<platform name="Windows-x86">
			<applicationDeployment>
				<nativeLibrary>CTest.dll</nativeLibrary>
				<initializer>initializer</initializer>
				<finalizer>finalizer</finalizer>
			</applicationDeployment>
		</platform>
	</platforms>
</extension>

这里需要注意的是id会映射到Air项目中的一个as类,nativeLibrary是刚才的dll名称,然后创建一个CTESTDLL.AS类

package com.bankcomm.Test
{
	import flash.events.StatusEvent;
	import flash.external.ExtensionContext;
	import flash.utils.ByteArray;
	
	import mx.controls.Alert;
	import mx.core.FlexGlobals;
	import mx.events.DynamicEvent;

	public class CTestDll
	{
		private var context:ExtensionContext;
		private var _callFuntion:Function;
		
		public function CTestDll()
		{
			try	{
				
				context = ExtensionContext.createExtensionContext('com.bankcomm.Test.ANETestDll', 'type');
				context.addEventListener(StatusEvent.STATUS,eventHandler);
				
			} catch (e:Error) {
				
			}
		}
		
		protected function eventHandler(e:StatusEvent):void
		{
			FlexGlobals.topLevelApplication.dispatchEvent(e);
		}
		
		public function sayHello(name:String, bytes:ByteArray):void
		{
			context.call('sayHello', name, bytes);
		}
		
		public function eventTest(bytes:ByteArray):void
		{
		    var m:Object;
			m=context.call("callBackHello",this,"callBuckTest");
			context.call('eventTest', bytes);
			
		}
		public function  callBuckTest():void
		{
			var my_name:String;
			my_name="lvshiyu";
		}
	}
}
这里创建了一个与C++DLL 连接的上下文 context,调用了普通函数  sayHello 和回调函数 callBackHello。创建好之后建立一个编译文件build.xml,这个文件是要使用ANT才能编译的,具体使用FLASH BUILDER 的ANT 的方法可以参照这篇文章,对于使用ANT 的方法,可以看看官网的这文章

<?xml version="1.0" ?>
<project default="packagenativeextensions">
    <!-- SDK properties -->
    <property name="SDK_HOME" value="D:\Program Files (x86)\adobe\Adobe Flash Builder 4.6\sdks\4.6.0"/>
	<property name="MXMLC.JAR" value="${SDK_HOME}/lib/mxmlc.jar"/>
	<property name="COMPC.JAR" value="${SDK_HOME}/lib/compc.jar"/>
	<property name="ADL" value="${SDK_HOME}/bin/adl.exe"/>
    <property name="ADT.JAR" value="${SDK_HOME}/lib/adt.jar"/>

    <!-- Project properties -->
    <property name="APP_ROOT_DIR" value="."/>
    <property name="APP_NAME" value="ANETest"/>
    <property name="APP_ROOT_FILE" value="${APP_NAME}.swf"/>
	<property name="APP_SOURCE_DIR" value="${APP_ROOT_DIR}/src"/>
    <property name="MAIN_SOURCE" value="${APP_SOURCE_DIR}/${APP_NAME}.mxml"/>
    <property name="APP_SOURCE_DESCRIPTOR" value="${APP_SOURCE_DIR}/${APP_NAME}-app.xml"/>
	<property name="KEYSTORE" location="${APP_ROOT_DIR}/wvw.p12"/>
	<property name="STOREPASS" value="geheim"/>
	
	<!-- Native Extensions -->
	<property name="NATIVE_EXTENSION_NAME" value="ANETestDll"/>
	<property name="NATIVE_EXTENSION_ACTIONSCRIPT_CLASSES" value="com.bankcomm.test.CTestDll" />
	<property name="NATIVE_EXTENSION_TMP_DIR" value="${APP_ROOT_DIR}/extensions/tmp"/>
	<property name="NATIVE_EXTENSION_BIN_DIR" value="${APP_ROOT_DIR}/extensions/bin"/>
	<property name="NATIVE_EXTENSION_SRC_DIR" value="${APP_ROOT_DIR}/extensions/src"/>
	<property name="NATIVE_EXTENSION_UNZIPPED_DIR" value="${APP_ROOT_DIR}/extensions/unzipped"/>
	
	<!-- Debug settings -->
    <property name="debug"  location="${APP_ROOT_DIR}/bin-debug"/>
	<property name="APP_DEBUG_DESCRIPTOR" value="${debug}/${APP_NAME}-app.xml"/>
    
     <target name="init" depends="clean">
     	<mkdir dir="${debug}"/>
     	<mkdir dir="${NATIVE_EXTENSION_BIN_DIR}"/>
     	<mkdir dir="${NATIVE_EXTENSION_UNZIPPED_DIR}"/>
    </target>
	
	<target name="compilenativeextensions" depends="init">
		<mkdir dir="${NATIVE_EXTENSION_TMP_DIR}"/>
		<java jar="${COMPC.JAR}" fork="true" failοnerrοr="true">
			<arg value="+flexlib=${SDK_HOME}/frameworks"/>
			<arg value="+configname=air"/>
			<arg value="-source-path"/>
			<arg value="src"/>
			<arg value="-include-classes"/>
			<arg value="${NATIVE_EXTENSION_ACTIONSCRIPT_CLASSES}"/>
			<arg value="-external-library-path"/>
			<arg value="${SDK_HOME}/frameworks/libs/air/airglobal.swc"/>
			<arg value="-output"/>
			<arg value="${NATIVE_EXTENSION_TMP_DIR}/nativeextensions.swc"/>
		</java>
		<unzip src="${NATIVE_EXTENSION_TMP_DIR}/nativeextensions.swc" dest="${NATIVE_EXTENSION_TMP_DIR}" />
	</target>
	
	<target name="packagenativeextensions" depends="compilenativeextensions">
		<!-- dll files -->
		<pathconvert property="nativeExtensionFiles" pathsep="' '" dirsep="/">
			<path>
				<fileset dir="${NATIVE_EXTENSION_SRC_DIR}" includes="**/*.dll"/>
			</path>
			<chainedmapper>
				<flattenmapper/>
			</chainedmapper>
		</pathconvert>
		<echo>native extension files: ${nativeExtensionFiles}</echo>
		<!-- flatten directory -->
		<copy todir="${NATIVE_EXTENSION_TMP_DIR}" flatten="true">
			<fileset dir="${NATIVE_EXTENSION_SRC_DIR}" />
		</copy>
		 <java jar="${ADT.JAR}" fork="true" dir="${NATIVE_EXTENSION_TMP_DIR}" failοnerrοr="true">
		 	<arg value="-package"/>
		 	<arg value="-storetype"/>
		 	<arg value="pkcs12"/>
		 	<arg value="-storepass"/>
		 	<arg value="${STOREPASS}"/>
		 	<arg value="-keystore"/>
		 	<arg value="${KEYSTORE}"/>
		 	<arg value="-tsa"/>
		 	<arg value="none"/>
		 	<arg value="-target"/>
		 	<arg value="ane"/>
		 	<arg value="${NATIVE_EXTENSION_NAME}.ane"/>
		 	<arg value="extension.xml"/>
		 	<arg value="-swc"/>
		 	<arg value="nativeextensions.swc"/>
		 	<arg value="-platform"/>
		 	<arg value="Windows-x86"/>
		 	<arg value="library.swf"/>
		 	<arg line="'${nativeExtensionFiles}'" />
		 </java>
		<copy file="${NATIVE_EXTENSION_TMP_DIR}/${NATIVE_EXTENSION_NAME}.ane" tofile="${NATIVE_EXTENSION_BIN_DIR}/${NATIVE_EXTENSION_NAME}.ane" />
		<delete dir="${NATIVE_EXTENSION_TMP_DIR}"/>
	</target>
	
	<target name="unpacknativeextensions" depends="packagenativeextensions">
		<unzip src="${NATIVE_EXTENSION_BIN_DIR}/${NATIVE_EXTENSION_NAME}.ane" dest="${NATIVE_EXTENSION_UNZIPPED_DIR}/${NATIVE_EXTENSION_NAME}.ane" />
	</target>

    <target name="debugcompile" depends="unpacknativeextensions">
        <java jar="${MXMLC.JAR}" fork="true" failοnerrοr="true">
            <arg value="-debug=true"/>
            <arg value="+flexlib=${SDK_HOME}/frameworks"/>
            <arg value="+configname=air"/>
            <arg value="-file-specs=${MAIN_SOURCE}"/>
            <arg value="-output=${debug}/${APP_ROOT_FILE}"/>
        </java>
    	<copy filtering="true" file="${APP_SOURCE_DESCRIPTOR}" tofile="${APP_DEBUG_DESCRIPTOR}" />
    	<replace file="${APP_DEBUG_DESCRIPTOR}">
    		<replacefilter token="[This value will be overwritten by Flash Builder in the output app.xml]" value="${APP_ROOT_FILE}"/>
    	</replace>
    </target>

    <target name="test" depends="debugcompile">
        <exec executable="${ADL}">
            <arg value="${APP_DEBUG_DESCRIPTOR}"/>
			<arg value="-extdir"/>
			<arg value="${NATIVE_EXTENSION_UNZIPPED_DIR}" />
            <arg value="${debug}"/>
          </exec> 
    </target>

    <target name="clean" description="clean up">
    	<delete dir="${debug}"/>
    	<delete dir="${NATIVE_EXTENSION_BIN_DIR}"/>
    	<delete dir="${NATIVE_EXTENSION_TMP_DIR}"/>
    	<delete dir="${NATIVE_EXTENSION_UNZIPPED_DIR}"/>
    </target>
</project>

SDK_HOME- 4.6 sdk位置

APP_NAME- Air项目名称

NATIVE_EXTENSION_NAME- 打包后ane的名称

NATIVE_EXTENSION_ACTIONSCRIPT_CLASSES- 映射的as类

成功后会在extensions\bin目录下出现一个ANETestDll.ane 

在项目的右键属性里面的构建里面添加本地扩展里面,将ANETESTDLL.ANE打勾,在项目的主文件里面的代码

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
					   xmlns:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx"
					   creationComplete="creationCompleteHandler(event)">
	<fx:Declarations>
		
	</fx:Declarations>
	
	<fx:Script>
		<![CDATA[
			import com.bankcomm.Test.ANETestDll;
			
			import mx.controls.Alert;
			import mx.events.FlexEvent;
			
			public var aneTestDll:ANETestDll;
			
			protected function creationCompleteHandler(event:FlexEvent):void
			{
				aneTestDll = new ANETestDll();
				addEventListener(StatusEvent.STATUS, statusHandler);
			}
			
			public function statusHandler(e:StatusEvent):void
			{
				var level:String = e.level;
				var code:String = e.code;
				Alert.show(code);
			}
			
			private function sayHello():void
			{
				var bytes:ByteArray = new ByteArray();
				aneTestDll.sayHello(txtName.text, bytes);
				var ret:String = bytes.readMultiByte(bytes.length,"chinese");
				Alert.show(ret);
			}
			
			private function eventTest():void
			{
				var bytes:ByteArray = new ByteArray();
				aneTestDll.eventTest(bytes);
			}
			
		]]>
	</fx:Script>
	
	<s:VGroup paddingTop="10" paddingLeft="10">
		<s:HGroup verticalAlign="baseline">
			<s:Label text="My Name is:"/>
			<s:TextInput id="txtName"/>
		</s:HGroup>
		<s:HGroup width="100%" horizontalAlign="right">
			<s:Button label="Say Hello" click="sayHello()"/>
		</s:HGroup>
		<s:Button label="Event Test" click="eventTest()"/>
	</s:VGroup>
	
</s:WindowedApplication>













  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值