千里马android Framework实战开发-你真的懂aidl转换吗(aidl命令转cpp)

Posted Android高级知识分享官

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了千里马android Framework实战开发-你真的懂aidl转换吗(aidl命令转cpp)相关的知识,希望对你有一定的参考价值。

csdn在线学习课程,课程咨询答疑和新课信息:QQ交流群:422901085进行课程讨论

android跨进程通信实战视频课程(加群获取优惠)

千里马android Framework实战开发-你真的懂aidl转换吗(aidl命令转cpp,aidl命令转java)

原来讲解aidl时候给大家讲过是转换成java文件情况,也给大家展示了怎么使用命令来吧aidl文件转换成java。
但是这里有个疑问了,难道aidl文件就只能转换成java文件么,难道不可以转换成cpp文件么?如果可以转换成cpp文件那是不是对我们native的层面的跨进程通信是不是也会变得非常非常方便,不用反复写transact,Parcel这样代码了。
这里的答案当然是:可以

那具体怎么做呢?怎么来用aidl命令把aidl文件转换成cpp呢?
具体我们来看aidl.exe命令的帮助:

D:\\adt-bundle-windows-x86-20140702\\adt-bundle-windows-x86-20140702\\sdk\\build-too                                                                                                                                                                                               ls\\29.0.3\\aidl.exe: option requires an argument -- h
usage:
D:\\adt-bundle-windows-x86-20140702\\adt-bundle-windows-x86-20140702\\sdk\\build-too                                                                                                                                                                                               ls\\29.0.3\\aidl.exe --lang={java|cpp} [OPTION]... INPUT...
   Generate Java or C++ files for AIDL file(s).

D:\\adt-bundle-windows-x86-20140702\\adt-bundle-windows-x86-20140702\\sdk\\build-too                                                                                                                                                                                               ls\\29.0.3\\aidl.exe --preprocess OUTPUT INPUT...
   Create an AIDL file having declarations of AIDL file(s).


D:\\adt-bundle-windows-x86-20140702\\adt-bundle-windows-x86-20140702\\sdk\\build-too                                                                                                                                                                                               ls\\29.0.3\\aidl.exe [OPTION]... INPUT [OUTPUT]
   Generate a Java file for an AIDL file.

OPTION:
  -I DIR, --include=DIR
          Use DIR as a search path for import statements.
  -m FILE, --import=FILE
          Import FILE directly without searching in the search paths.
  -p FILE, --preprocessed=FILE
          Include FILE which is created by --preprocess.
  -d FILE, --dep=FILE
          Generate dependency file as FILE. Don't use this when
          there are multiple input files. Use -a then.
  -o DIR, --out=DIR
          Use DIR as the base output directory for generated files.
  -h DIR, --header_out=DIR
          Generate C++ headers under DIR.
  -a
          Generate dependency file next to the output file with the
          name based on the input file.
  -b
          Trigger fail when trying to compile a parcelable.
  --ninja
          Generate dependency file in a format ninja understands.
  --structured
          Whether this interface is defined exclusively in AIDL.
          It is therefore a candidate for stabilization.
  -t, --trace
          Include tracing code for systrace. Note that if either
          the client or service code is not auto-generated by this
          tool, that part will not be traced.
  --transaction_names
          Generate transaction names.
  --apimapping
          Generates a mapping of declared aidl method signatures to
          the original line number. e.g.:
              If line 39 of foo/bar/IFoo.aidl contains:              void doFoo(                                                                                                                                                                                               int bar, String baz);
              Then the result would be:
              foo.bar.Baz|doFoo|int,String,|void
              foo/bar/IFoo.aidl:39
  -v VER, --version=VER
          Set the version of the interface and parcelable to VER.
          VER must be an interger greater than 0.
  --log
          Information about the transaction, e.g., method name, argument
          values, execution time, etc., is provided via callback.
  --help
          Show this help.

INPUT:
  An AIDL file.

OUTPUT:
  Path to the generated Java or C++ source file. This is ignored when
  -o or --out is specified or the number of the input files are
  more than one.
  For Java, if omitted, Java source file is generated at the same
  place as the input AIDL file,

HEADER_DIR:
  Path to where C++ headers are generated.

相信大家一定看到了c++相关字眼,所以这里就可以基本确认完全可以,具体怎么做:
aidl.exe --lang={java|cpp} [OPTION]… INPUT…

这一句吸引了我,–lang={java|cpp}明显就是可以让大家选择是生成cpp还是java的,那我这边就直接把我探索的命令分享出来给大家:

aidl.exe --lang=cpp -IF:\\binder_drivers_code\\ServiceDemo\\app\\src\\main\\aidl\\com\\example\\servicedemo  F:\\binder_drivers_code\\ServiceDemo\\app\\src\\main\\aidl\\com\\example\\servicedemo\\IStudentInterface1.aidl -o f:\\ --header_out f:\\

执行完毕就cpp就在f盘根目录,但是这里要注意哦,是带有包文件夹的:


打开IStudentInterface1.cpp:

#include <com/example/servicedemo/IStudentInterface1.h>
#include <com/example/servicedemo/BpStudentInterface1.h>

namespace com {

namespace example {

namespace servicedemo {

IMPLEMENT_META_INTERFACE(StudentInterface1, "com.example.servicedemo.IStudentInterface1")

::android::IBinder* IStudentInterface1Default::onAsBinder() {
  return nullptr;
}

::android::binder::Status IStudentInterface1Default::getStudentId(const ::android::String16&, int32_t* ) {
  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
}

::android::binder::Status IStudentInterface1Default::addStudentId(const ::android::String16&) {
  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
}

}  // namespace servicedemo

}  // namespace example

}  // namespace com
#include <com/example/servicedemo/BpStudentInterface1.h>
#include <binder/Parcel.h>
#include <android-base/macros.h>

namespace com {

namespace example {

namespace servicedemo {

BpStudentInterface1::BpStudentInterface1(const ::android::sp<::android::IBinder>& _aidl_impl)
    : BpInterface<IStudentInterface1>(_aidl_impl){
}

::android::binder::Status BpStudentInterface1::getStudentId(const ::android::String16& name, int32_t* _aidl_return) {
  ::android::Parcel _aidl_data;
  ::android::Parcel _aidl_reply;
  ::android::status_t _aidl_ret_status = ::android::OK;
  ::android::binder::Status _aidl_status;
  _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_data.writeString16(name);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = remote()->transact(::android::IBinder::FIRST_CALL_TRANSACTION + 0 /* getStudentId */, _aidl_data, &_aidl_reply);
  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IStudentInterface1::getDefaultImpl())) {
     return IStudentInterface1::getDefaultImpl()->getStudentId(name, _aidl_return);
  }
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  if (!_aidl_status.isOk()) {
    return _aidl_status;
  }
  _aidl_ret_status = _aidl_reply.readInt32(_aidl_return);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_error:
  _aidl_status.setFromStatusT(_aidl_ret_status);
  return _aidl_status;
}

::android::binder::Status BpStudentInterface1::addStudentId(const ::android::String16& id) {
  ::android::Parcel _aidl_data;
  ::android::Parcel _aidl_reply;
  ::android::status_t _aidl_ret_status = ::android::OK;
  ::android::binder::Status _aidl_status;
  _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_data.writeString16(id);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = remote()->transact(::android::IBinder::FIRST_CALL_TRANSACTION + 1 /* addStudentId */, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_ONEWAY);
  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IStudentInterface1::getDefaultImpl())) {
     return IStudentInterface1::getDefaultImpl()->addStudentId(id);
  }
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_error:
  _aidl_status.setFromStatusT(_aidl_ret_status);
  return _aidl_status;
}

}  // namespace servicedemo

}  // namespace example

}  // namespace com
#include <com/example/servicedemo/BnStudentInterface1.h>
#include <binder/Parcel.h>

namespace com {

namespace example {

namespace servicedemo {

::android::status_t BnStudentInterface1::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
  ::android::status_t _aidl_ret_status = ::android::OK;
  switch (_aidl_code) {
  case ::android::IBinder::FIRST_CALL_TRANSACTION + 0 /* getStudentId */:
  {
    ::android::String16 in_name;
    int32_t _aidl_return;
    if (!(_aidl_data.checkInterface(this))) {
      _aidl_ret_status = ::android::BAD_TYPE;
      break;
    }
    _aidl_ret_status = _aidl_data.readString16(&in_name);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    ::android::binder::Status _aidl_status(getStudentId(in_name, &_aidl_return));
    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    if (!_aidl_status.isOk()) {
      break;
    }
    _aidl_ret_status = _aidl_reply->writeInt32(_aidl_return);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
  }
  break;
  case ::android::IBinder::FIRST_CALL_TRANSACTION + 1 /* addStudentId */:
  {
    ::android::String16 in_id;
    if (!(_aidl_data.checkInterface(this))) {
      _aidl_ret_status = ::android::BAD_TYPE;
      break;
    }
    _aidl_ret_status = _aidl_data.readString16(&in_id);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    ::android::binder::Status _aidl_status(addStudentId(in_id));
  }
  break;
  default:
  {
    _aidl_ret_status = ::android::BBinder::onTransact(_aidl_code, _aidl_data, _aidl_reply, _aidl_flags);
  }
  break;
  }
  if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
  }
  return _aidl_ret_status;
}

}  // namespace servicedemo

}  // namespace example

}  // namespace com

主要有的是BnStudentInterface1,BpStudentInterface1两个类,其实和java的基本完全一样,就不过多分析

以上是关于千里马android Framework实战开发-你真的懂aidl转换吗(aidl命令转cpp)的主要内容,如果未能解决你的问题,请参考以下文章

千里马Android Framework实战开发-native程序之间binder通信实战案例分析

千里马Android Framework实战开发-native程序之间binder通信实战案例分析

千里马Android Framework实战开发-跨进程通信专题博客总结

千里马Android Framework实战开发-跨进程通信专题课表介绍

千里马android framework实战开发-binder驱动之oneway导致的transaction failed

千里马android framework实战开发-binder驱动之oneway导致的transaction failed