哪家公司做网站/张家界seo
一. 概述
这篇文章主要是想整理并且分析CommonAPI代码生成工具根据fidl和fdepl配置文件生成出来的代码的结构和作用。
二. fidl
用户根据业务需求在fidl文件中定义业务服务接口的结构以及自定义数据类型,然后使用core生成工具传入fidl文件生成该fidl的核心层Proxy和Stub以及配套的相关代码。
例如官方范例上的HelloWorld(https://github.com/COVESA/capicxx-core-tools/blob/master/CommonAPI-Examples/E01HelloWorld/fidl/E01HelloWorld.fidl),使用生成工具commonapi-core-generator-linux-x86_64输入该fidl文件可以生成HelloWorld.hpp,HelloWorldProxy.hpp,HelloWorldProxyBase.hpp,HelloWorldStub.hpp,HelloWorldStubDefault.hpp这5个代码文件。
2.1 interface
一个fidl文件对应一个CommonAPI的interface,对于C++来说,要定义一个interface,当然是使用一个抽象类来定义了,这个抽象类就是HelloWorld.hpp文件中的HelloWorld类了。
namespace v1 {
namespace commonapi {class HelloWorld {
public:virtual ~HelloWorld() { }static inline const char* getInterface(); // HelloWorld业务的CommonAPI接口名称static inline CommonAPI::Version getInterfaceVersion(); // HelloWorld业务的CommonAPI接口版本
};const char* HelloWorld::getInterface() {return ("commonapi.HelloWorld:v1_0");
}CommonAPI::Version HelloWorld::getInterfaceVersion() {return CommonAPI::Version(1, 0);
}} // namespace commonapi
} // namespace v1
当看到core工具生成的HelloWorld接口类,感觉有点奇怪,这个HelloWorld接口类只定义并且实现了两个关于接口信息的函数(接口名称和接口版本信息),而fidl中关于HelloWorld接口中的业务函数sayHello在生成的HelloWorld接口类中确没有
// HelloWorld.fidl
package commonapiinterface HelloWorld {version {major 1 minor 0}method sayHello { // 该函数没有生成在HelloWorld接口类中in {String name}out {String message}}
}
对于为什么生成的HelloWorld接口类中没有定义sayHello函数的原因,个人阅读完生成的代码后理解是,由于HelloWorld.fidl生成的核心层Proxy以及Stub代码在sayHello函数上的定义是不兼容的,而HelloWorld接口类又是核心层HelloWorldProxy和HelloWorldStub的父类,因此无法将sayHello函数的申明放入HelloWorld接口类中。
HelloWorld接口类中的getInterface和getInterfaceVersion函数是为了给CommonAPI核心层代码库创建核心层Proxy/Stub的时候使用的,代码如下:
// 代码文件/usr/local/include/CommonAPI-3.2/CommonAPI/Runtime.hpp
template<template<typename ...> class ProxyClass_, typename ... AttributeExtensions_>COMMONAPI_EXPORT std::shared_ptr<ProxyClass_<AttributeExtensions_...>>buildProxy(const std::string &_domain,const std::string &_instance,const ConnectionId_t &_connectionId = DEFAULT_CONNECTION_ID) {std::shared_ptr<Proxy> proxy= createProxy(_domain,//这里的ProxyClass就是HelloWorldProxy类,调用HelloWorldProxy的父类HelloWorld中的getInterfaceProxyClass_<AttributeExtensions_...>::getInterface(), _instance,_connectionId);if (proxy) {return std::make_shared<ProxyClass_<AttributeExtensions_...>>(proxy);}return nullptr;}
2.2 Proxy
在核心层生成了HelloWorldProxy.hpp和HelloWorldProxyBase.hpp两个代码文件,里面分别定义了HelloWorldProxy和HelloWorldProxyBase两个类。
其中,HelloWorldProxyBase是HelloWorldProxy的一个父类,其中包含了fidl中sayHello函数的相关定义(包括了同步调用和异步调用两种)
class HelloWorldProxyBase: virtual public CommonAPI::Proxy {
public:typedef std::function<void(const CommonAPI::CallStatus&, const std::string&)> SayHelloAsyncCallback; // 异步调用的回调通知接口virtual void sayHello(std::string _name, CommonAPI::CallStatus &_internalCallStatus, std::string &_message, const CommonAPI::CallInfo *_info = nullptr) = 0; // 同步调用接口virtual std::future<CommonAPI::CallStatus> sayHelloAsync(const std::string &_name, SayHelloAsyncCallback _callback = nullptr, const CommonAPI::CallInfo *_info = nullptr) = 0; // 异步调用接口virtual std::future<void> getCompletionFuture() = 0;
};
HelloWorldProxy类中实现了HelloWorldProxyBase父类中定义的sayHello相关接口:
template <typename ... _AttributeExtensions>
void HelloWorldProxy<_AttributeExtensions...>::sayHello(std::string _name, CommonAPI::CallStatus &_internalCallStatus, std::string &_message, const CommonAPI::CallInfo *_info) {delegate_->sayHello(_name, _internalCallStatus, _message, _info);
}
可以看到,HelloWorldProxy内部实现fidl中定义的接口时,还依赖了一个delegate_对象,这个delegatge_对象是HelloWorldProxyBase类型的共享指针
template <typename ... _AttributeExtensions>
class HelloWorldProxy: virtual public HelloWorld,virtual public HelloWorldProxyBase,virtual public _AttributeExtensions... {public:...private:std::shared_ptr< HelloWorldProxyBase> delegate_;
};
这里就有点不对了,前面说过HelloWorldProxy的一个父类就是HelloWorldProxyBase,难道HelloWorldProxy对象内部的这个delegate_共享指针是指向自己的?当然不是,在src-gen目录下查找还有没有其他类是HelloWorldProxy,结果看到HelloWorldProxyBase类也是HelloWorldSomeIPProxy类的父类,HelloWorldSomeIPProxy是通过commonapi-someip-generator-linux-x86_64工具生成的绑定层的Proxy类。
也就是说核心层的Proxy是依赖绑定层的Proxy的,绑定层的内部会产生依赖所绑定中间件的代码来实现fidl中定义的接口函数。
2.3 Stub
在核心层生成了HelloWorldStub.hpp,HelloWorldStubDefault.hpp这两个代码文件,其中包含HelloWorldStubAdapter,HelloWorldStubRemoteEvent, HelloWorldStub以及HelloWorldStubDefault这四个类,这四个类的关系如下:
首先是HelloWorldStubAdapter类,其继承于CommonAPI::StubAdapter(实现了CommonAPI地址提供接口getAddress)和HelloWorld(实现了接口信息提供方法getInterface和getInterfaceVersion)。
所谓CommonAPI地址,包含三个成员(domain, interface, instance),这三个成员都是字符串:
namespace CommonAPI {
class Address {
public:COMMONAPI_EXPORT Address();...private:std::string domain_; // 所在域std::string interface_; // 接口名称std::string instance_; // 实例名称friend COMMONAPI_EXPORT std::ostream &operator<<(std::ostream &_out, const Address &_address);
};
}
CommonAPI::StubAdapter中CommonAPI地址的来源是绑定层的StubAdapter(CommonAPI::SomeIP::StubAdapter)在初始化的时候赋值的
// Stub.hpp
namespace CommonAPI {class StubAdapter {public:virtual ~StubAdapter() {}inline const Address &getAddress() const { return address_; }protected:Address address_; // 在绑定层的StubAdapter中赋值};
}// StubAdapter.cpp
namespace CommonAPI {
namespace SomeIP {
class StubAdapter: virtual public CommonAPI::StubAdapter, public InterfaceHandler { // 继承自核心层的StubAdapter
...
void
StubAdapter::init(std::shared_ptr<StubAdapter> instance) {(void) instance;// AddressTranslator保存了绑定层地址和核心层地址的映射关系// 这个映射关系在绑定层StubAdapter的initializer函数中插入的AddressTranslator::get()->translate(someipAddress_, address_); // address_是CommonAPI::StubAdapter中的成员变量
}
...
}
}
其次是HelloWorldStubRemoteEvent类,这个类目前基本是空的,因为这是个和属性相关的类,如果你的fidl中没有定义属性成员,那么生成的StubRemoteEvent类可能就是空的,对照官网上https://github.com/COVESA/capicxx-core-tools/tree/master/CommonAPI-Examples/E02Attributes这个带属性的范例生成的代码可以看到,有属性的fidl生成的StubRemoteEvent类是定义了一些属性相关的接口的,例如:
class E02AttributesStubRemoteEvent
{
public:virtual ~E02AttributesStubRemoteEvent() { }/// Verification callback for remote set requests on the attribute xvirtual bool onRemoteSetXAttribute(const std::shared_ptr<CommonAPI::ClientId> _client, int32_t _value) = 0;/// Action callback for remote set requests on the attribute xvirtual void onRemoteXAttributeChanged() = 0;/// Verification callback for remote set requests on the attribute a1virtual bool onRemoteSetA1Attribute(const std::shared_ptr<CommonAPI::ClientId> _client, ::v1::commonapi::examples::CommonTypes::a1Struct _value) = 0;/// Action callback for remote set requests on the attribute a1virtual void onRemoteA1AttributeChanged() = 0;
};
也就是说,生成的这个StubRemoteEent类是个关于事件通知的接口类,是需要用户自己来实现内部接口来接收属性的变化通知。
接者是HelloWorldStub类,这也是个接口类,继承自CommonAPI::Stub,CommonAPI::Stub最重要的工作是和CommonAPI::StubHelper打交道
namespace CommonAPI {
template<typename StubAdapter_, typename StubRemoteEventHandler_>
class Stub: public virtual StubBase {
public:// 初始化StubAdaptervirtual StubRemoteEventHandler_* initStubAdapter(const std::shared_ptr<StubAdapter_> &_stubAdapter) = 0;// 返回StubAdapterinline const std::shared_ptr<StubAdapter_> getStubAdapter() const { return stubAdapter_.lock(); }protected:std::weak_ptr<StubAdapter_> stubAdapter_;
因此,HelloWorldStub类包含了初始化和返回StubAdapter的接口,此外还增加了fidl中sayHello接口的申明,也就是说HelloWorldStub接口类的实现类至少要实现initStubAdapter,getStubAdapter和sayHello三个接口。
最后就是HelloWorldStubDefault类,它就是实现上面HelloWorldStub接口类中三个接口的实现类,代码如下:
class COMMONAPI_EXPORT_CLASS_EXPLICIT HelloWorldStubDefault: public virtual HelloWorldStub {
public:COMMONAPI_EXPORT HelloWorldStubDefault(): remoteEventHandler_(this),interfaceVersion_(HelloWorld::getInterfaceVersion()) {}COMMONAPI_EXPORT const CommonAPI::Version& getInterfaceVersion(std::shared_ptr<CommonAPI::ClientId> _client) {(void)_client;return interfaceVersion_; // 返回接口版本}COMMONAPI_EXPORT HelloWorldStubRemoteEvent* initStubAdapter(const std::shared_ptr< HelloWorldStubAdapter> &_adapter) {CommonAPI::Stub<HelloWorldStubAdapter, HelloWorldStubRemoteEvent>::stubAdapter_ = _adapter;return &remoteEventHandler_;}COMMONAPI_EXPORT virtual void sayHello(const std::shared_ptr<CommonAPI::ClientId> _client, std::string _name, sayHelloReply_t _reply) {(void)_client;(void)_name;std::string message = "";_reply(message);}...
HelloWorldStubDefault类是一个默认的生成的Stub接口实现类,里面的函数实现大多数是无用的,用户需要在HelloWorldStubDefault这个生成的默认Stub实现类上再做一次实现(继承并且实现),例如代码实例中的HelloWorldStubImpl类那样。
三. fdepl
fdepl文件生成绑定层的代码,会生成HelloWorldSomeIPProxy,HelloWorldSomeIPStubAdapterInternal,HelloWorldSomeIPStubAdapter这几个绑定层的类。
3.1 Proxy
HelloWorldSomeIPProxy类是绑定层生成的Proxy类,其构造时需要传入绑定层地址(CommonAPI::SomeIP::Address),CommonAPI::SomeIP::Address包含SomeIP服务实例的信息:
namespace CommonAPI {
namespace SomeIP {class COMMONAPI_EXPORT Address {...
private:service_id_t service_; // 服务IDinstance_id_t instance_; // 实例IDmajor_version_t major_version_; // Max版本号minor_version_t minor_version_; // Min版本号
}
}
}
先来看下创建HelloWorldSomeIPProxy的过程,首先,用户需要在自己的应用程序中创建核心层的Proxy(HelloWorldProxy)
// HelloWorldClient.cpp
int main() {...// CommonAPI::Address// {// domainid = "local"// interface = HelloWorld::getInterface = "commonapi.HelloWorld:v1_0"// instance = "test"// }std::shared_ptr<HelloWorldProxy<>> myProxy = runtime->buildProxy<HelloWorldProxy>("local", "test");...
}
可以看到,创建核心层HelloWorldProxy的时候,对应的CommonAPI::Address地址已经提供出来了,然后runtime在创建的时候,会在调用核心层的工厂类(CommonAPI::SomeIP::Factory)的createProxy创建绑定层的HelloWorldSomeIPProxy对象,这个时候就需要从AddressTranslator中获取绑定层地址(SomeipIP的服务和实例信息)
// Factory.cppstd::shared_ptr<CommonAPI::Proxy>
Factory::createProxy(const std::string &_domain,const std::string &_interface, const std::string &_instance,const ConnectionId_t &_connectionId) {auto proxyCreateFunctionsIterator= proxyCreateFunctions_.lower_bound(_interface);// 查找是否为该interface注册过SomeIP绑定层的Proxy的创建函数if (proxyCreateFunctionsIterator!= proxyCreateFunctions_.end()) { // 找到该CommonAPI interface注册的SomeIP绑定层Proxy创建函数...CommonAPI::Address address(_domain, itsInterface, _instance);Address someipAddress;// 在AddressTranslator中查找CommonAPI地址对应的SomeIP地址if (AddressTranslator::get()->translate(address, someipAddress)) {std::shared_ptr<Connection> itsConnection= getConnection(_connectionId);if (itsConnection) {// 使用注册的Proxy创建函数createHelloWorldSomeIPProxy创建HelloWorldSomeIPProxy// 传入的CommonAPI::SomeIP::Address为{0x1234, 0x1, 1, 0}std::shared_ptr<Proxy> proxy= proxyCreateFunctionsIterator->second(someipAddress, itsConnection);if (proxy && proxy->init())return proxy;}}}COMMONAPI_ERROR("Creating proxy for \"", _domain, ":", _interface, ":",_instance, "\" failed!");return nullptr;
}
AddressTranslator中CommonAPI地址和SomeIP绑定层地址的对应关系在生成的绑定层HelloWorldSomeIPProxy.cpp中插入的:
// HelloWorldSomeIPProxy.cpp
void initializeHelloWorldSomeIPProxy() {// 插入地址对应关系CommonAPI::SomeIP::AddressTranslator::get()->insert("local:commonapi.HelloWorld:v1_0:test", // CommonAPI Address0x1234, 0x1, 1, 0); // CommonAPI::SomeIP Address// 注册绑定层SomeIP创建函数CommonAPI::SomeIP::Factory::get()->registerProxyCreateMethod("commonapi.HelloWorld:v1_0", // CommonAPI interface&createHelloWorldSomeIPProxy); // SomeIP Proxy create function
}std::shared_ptr<CommonAPI::SomeIP::Proxy> createHelloWorldSomeIPProxy(const CommonAPI::SomeIP::Address &_address,const std::shared_ptr<CommonAPI::SomeIP::ProxyConnection> &_connection) {return std::make_shared< HelloWorldSomeIPProxy>(_address, _connection);
}
然后,生成的绑定层HelloWorldSomeIPProxy也是需要实现fidl中定义的sayHello接口的,其实现主要是依赖Deployment类来包装输入的参数,然后通过ProxyHelper类来完成参数的序列化和中间件通信接口的调用(ProxyHelper::callMethod):
void HelloWorldSomeIPProxy::sayHello(std::string _name, CommonAPI::CallStatus &_internalCallStatus, std::string &_message, const CommonAPI::CallInfo *_info) {CommonAPI::Deployable< std::string, CommonAPI::SomeIP::StringDeployment> deploy_name(_name, static_cast< CommonAPI::SomeIP::StringDeployment* >(nullptr)); // 输入参数CommonAPI::Deployable< std::string, CommonAPI::SomeIP::StringDeployment> deploy_message(static_cast< CommonAPI::SomeIP::StringDeployment* >(nullptr)); // 返回参数// 依赖ProxyHelper类发起someip的Method请求(REQUEST-RESPONSE)CommonAPI::SomeIP::ProxyHelper<...>::callMethodWithReply( // ProxyHelper类是个静态类,内部都是静态方法,不保存成员*this, // 主要是提供HelloWorldSomeIPProxy内部的Connection指针CommonAPI::SomeIP::method_id_t(0x7b),false,false,(_info ? _info : &CommonAPI::SomeIP::defaultCallInfo),deploy_name,_internalCallStatus,deploy_message);_message = deploy_message.getValue();
}
而ProxyHelper的callMethod函数则依赖Connetion类来完成中间件接口的调用。
template <typename Proxy_ = Proxy>
static void callMethod(...) {if (_proxy.isAvailable()) { // 对端service为可用状态// 首先序列化参数OutputStream outputStream(_methodCall, _isLittleEndian);const bool success = SerializableArguments<InArgs_...>::serialize(outputStream, _inArgs...);...// 通过Connection指针调用到vsomeip中间件接口bool success = _proxy.getConnection()->sendMessage(_methodCall); ...} else {...}
}
3.2 Stub
HelloWorldSomeIPStubAdapterInternal是HelloWorldSomeIPStubAdapter的父类,此外,HelloWorldSomeIPStubAdapterInternal类也是绑定层对于核心层HelloWorldStubAdapter接口类的实现。
总体来说,StubAdapter类是在Stub和中间件之间做适配功能的类,并且实现了核心层的StubAdapter接口类中定义的接口。
先看下HelloWorldSomeIPStubAdapterInternal类,HelloWorldSomeIPStubAdapterInternal继承自核心层生成的HelloWorldStubAdapter接口和CommonAPI::SomeIP::StubAdapterHelper类。
HelloWorldSomeIPStubAdapterInternal类有获取内部属性的成员,其中包括Version信息的属性的getHelloWorldInterfaceVersionStubDispatcher成员,如果fidl中定义了业务的属性,则还会包含该业务属性的StubDispatcher成员,例如https://github.com/COVESA/capicxx-core-tools/tree/master/CommonAPI-Examples/E02Attributes 中fdepl生成的E02AttributesSomeIPStubAdapter.hpp文件中,E02AttributesSomeIPStubAdapterInternal类就有getXAttributeStubDispatcher,getA1AttributeStubDispatcher和getE02AttributesInterfaceVersionStubDispatcher,其中getXAttributeStubDispatcher对应fidl中定义的属性x,getA1AttributeStubDispatcher对应fidl中定义的属性a1。
SomeIPStubAdapterInternal类内部的StubDispatcher成员都是GetAttributeStubDispatcher类型的,实现了StubDispatcher接口,查看GetAttributeStubDispatcher类的实现可以看到内部成员函数dispatchMessage,这个函数就是通过Connection类调用SomeIP中间件将属性值通过消息的方式发送给客户端:
template <typename StubClass_, typename AttributeType_, typename AttributeDepl_ = EmptyDeployment>
class GetAttributeStubDispatcher: public StubDispatcher<StubClass_> {
public:...bool dispatchMessage(const Message &message, const std::shared_ptr<StubClass_> &stub,RemoteEventHandlerType* _remoteEventHandler,std::shared_ptr<ProxyConnection> _connection) {...return sendAttributeValueReply(message, stub, _connection);}protected: inline bool sendAttributeValueReply(const Message &message, const std::shared_ptr<StubClass_>& stub,std::shared_ptr<ProxyConnection> _connection) {...return _connection->sendMessage(reply);}...}
当服务端进程收到客户端发送的对属性访问的SOMEIP method消息触发该接口的调用,调用栈如下:
Connection::handleStubReceive // 从中间件收到client发送的消息// 处理消息(根据消息中的serviceID, instanceID找到对应的CommonAPI::SomeIP::StubAdapter// 例如E02AttributesSomeIPStubAdapterInternal,HelloWorldSomeIPStubAdapterInternal StubManager::handleMessage StubAdapterHelper::onInterfaceMessage // StubAdapterHelper也是E02AttributesSomeIPStubAdapterInternal的父类StubAdapterHelper::findDispatcherAndHandleStubDispatcher::dispatchMessage // 内部调用Stub对应的get属性值的方法获取当前属性值
当服务端进程将属性的值通过SOMEIP消息回复给客户端的时候,首先是需要知道当前服务instance中该属性的值对不对,fidl文件生成的核心层Stub中提供这个属性的值的获取方法:
// src-gen/v1/commonapi/examples/E02AttributesStubDefault.hpp
COMMONAPI_EXPORT virtual const int32_t &getXAttribute() {return xAttributeValue_;
}
也就是说如果有Stub对象,就可以调用其getXAttribute方法获取其x属性的当前值,然后在E02AttributesSomeIPStubAdapterInternal的构造函数中可以看到,HelloWorldSomeIPStubAdapterInternal构造函数中创建x属性对应的getXAttributeStubDispatcher对象时提供getXAttribute方法:
E02AttributesSomeIPStubAdapterInternal(...getXAttributeStubDispatcher(&::v1::commonapi::examples::E02AttributesStub::lockXAttribute,&::v1::commonapi::examples::E02AttributesStub::getXAttribute, // 注册到内部getStubFunctor_成员中false,_stub->hasElement(0)),22...
}
getXAttributeStubDispatcher是GetAttributeStubDispatcher类型的,其dispatchMessage方法中可以看到对get属性值方法的调用:
class GetAttributeStubDispatcher: public StubDispatcher<StubClass_> {
public:...bool dispatchMessage(const Message &message, const std::shared_ptr<StubClass_> &stub,...return sendAttributeValueReply(message, stub, _connection);}
protected:inline bool sendAttributeValueReply(const Message &message, const std::shared_ptr<StubClass_>& stub,std::shared_ptr<ProxyConnection> _connection) {Message reply = message.createResponseMessage();OutputStream outputStream(reply, isLittleEndian_);...// 获取属性值auto deployable = CommonAPI::Deployable<AttributeType_, AttributeDepl_>((stub.get()->*getStubFunctor_)(clientId), depl_);outputStream << deployable; // 写入消息outputStream.flush();return _connection->sendMessage(reply); // 发送属性值get-method消息的回复消息}
}
HelloWorldSomeIPStubAdapter继承了HelloWorldSomeIPStubAdapterInternal,也就具备了通过绑定层调用SomeIP中间件进行通信的功能,在此基础上,主要增加了一个功能,就是在构造函数中增加了SomeIP地址和Connection对象的传入,有了这两个对象,HelloWorldSomeIPStubAdapterInternal的SomeIP通信功能才能真正工作起来。
public:HelloWorldSomeIPStubAdapter(const CommonAPI::SomeIP::Address &_address,const std::shared_ptr<CommonAPI::SomeIP::ProxyConnection> &_connection,const std::shared_ptr<CommonAPI::StubBase> &_stub): CommonAPI::SomeIP::StubAdapter(_address, _connection),HelloWorldSomeIPStubAdapterInternal<_Stub, _Stubs...>(_address, _connection, _stub) {}
那么这个构造函数什么时候调用的呢?是CommonAPI::SomeIP::Factory调用的,之前在核心层说过,生成的绑定层Stub代码会将HelloWorldSomeIPStubAdapter的创建函数和对应的CommonAPI::Address注册给Factory:
void initializeHelloWorldSomeIPStubAdapter() {CommonAPI::SomeIP::AddressTranslator::get()->insert("local:commonapi.HelloWorld:v1_0:test",0x1234, 0x1, 1, 0);CommonAPI::SomeIP::Factory::get()->registerStubAdapterCreateMethod( // 注册HelloWorldSomeIPStubAdapter的创建函数"commonapi.HelloWorld:v1_0",&createHelloWorldSomeIPStubAdapter);
}
当我们在服务端代码中注册我们的HelloWorldStubImpl时,通过核心层调用到绑定层的SomeIP::Factory进行HelloWorldSomeIPStubAdapter对象的创建:
int main() {std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::get();std::shared_ptr<HelloWorldStubImpl> myService =std::make_shared<HelloWorldStubImpl>();runtime->registerService("local", "test", myService); // 这一步会调用到SomeIP::Factory创建HelloWorldSomeIPStubAdapter...
}
相关文章:

CommonAPI学习笔记-2
一. 概述 这篇文章主要是想整理并且分析CommonAPI代码生成工具根据fidl和fdepl配置文件生成出来的代码的结构和作用。 二. fidl 用户根据业务需求在fidl文件中定义业务服务接口的结构以及自定义数据类型,然后使用core生成工具传入fidl文件生成该fidl的核心…...

ISP代理与住宅代理的区别
代理充当用户和互联网之间的中介,在增强安全性、隐私和可访问性方面提供多种功能。在众多代理类型中,ISP和住宅代理脱颖而出,各自拥有不同的功能和应用程序。 一、ISP代理 ISP代理,俗称Internet服务提供商代理,通过其…...

[25] cuda 应用之 nppi 实现图像色彩调整
[25] cuda 应用之 nppi 实现图像色彩调整 在 NPPI(NVIDIA Performance Primitives)中,图像色彩调整通常包括以下几种操作: 亮度调整:增加或减少图像的亮度。对比度调整:增强或减弱图像的对比度。饱和度调整:增强或减弱图像的颜色饱和度。色调调整:改变图像的色调(通常…...

Java 大视界 -- Java 大数据在智慧文旅中的应用与体验优化(74)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...

PyTorch快速入门
Anaconda Anaconda 是一款面向科学计算的开源 Python 发行版本,它集成了众多科学计算所需的库、工具和环境管理系统,旨在简化包管理和部署,提升开发与研究效率。 核心组件: Conda:这是 Anaconda 自带的包和环境管理…...

100.7 AI量化面试题:如何利用新闻文本数据构建交易信号?
目录 0. 承前1. 解题思路1.1 数据处理维度1.2 分析模型维度1.3 信号构建维度 2. 新闻数据获取与预处理2.1 数据获取接口2.2 文本预处理 3. 情感分析与事件抽取3.1 情感分析模型3.2 事件抽取 4. 信号生成与优化4.1 信号构建4.2 信号优化 5. 策略实现与回测5.1 策略实现 6. 回答话…...

CF 465B.Inbox (100500)(Java实现)
题目分析 计算读取所有未读邮件所需的步数,其中1代表未读,0代表已读 思路分析 遍历邮件,如果当前是未读,那么所需步数1,如果下一封也是未读,不用管(遍历后会直接1),如果下一封是已读࿰…...

微信小程序获取openid和其他接口同时并发请求如何保证先获取到openid
在微信小程序中,如果你需要并发请求获取 openid 和其他接口的数据,并且希望确保先获取到 openid 之后再进行后续操作,可以考虑以下几种方法: 方法一:使用 Promise 链 1, 先请求 openid:使用 Promise 来请求 openid。 2, 在获取到 openid 后再请求其他接口。 function g…...

实现动态卡通笑脸的着色器实现
大家好!我是 [数擎 AI],一位热爱探索新技术的前端开发者,在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情,欢迎关注我的文章,我们一起成长、进步! 开发领域:前端开发 | A…...

DeepSeek R1 模型解读与微调
DeepSeek R1 模型是 DeepSeek 团队推出的一款重要的大语言模型,旨在通过强化学习提升大型语言模型的推理能力。 模型架构 DeepSeek-R1-Zero DeepSeek-R1-Zero 是 DeepSeek 团队推出的第一代推理模型,完全依靠强化学习(RL)训练&…...

YOLOv11实时目标检测 | 摄像头视频图片文件检测
在上篇文章中YOLO11环境部署 || 从检测到训练https://blog.csdn.net/2301_79442295/article/details/145414103#comments_36164492,我们详细探讨了YOLO11的部署以及推理训练,但是评论区的观众老爷就说了:“博主博主,你这个只能推理…...

Node.js学习指南
一、模块化规范 nodejs使用的模块化规范 叫做 common.js 规范: 每一个模块都有独立的作用域 代码在各自模块中执行 不会造成全局污染 每一个模块都是一个独立的文件(module对象) 模块可以被多次加载(module.exports 属性) 但是仅…...

2.5学习总结
今天看了二叉树,看的一脸懵,写了两道题 P4913:二叉树深度 #include <stdio.h> #include <stdlib.h> struct hly {int left;int right; }tree[1000005]; int hulingyun(int x) {if(x0)return 0;return 1max(hulingyun(tree[x].le…...

java进阶文章链接
java 泛型:java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一 Java 泛型,你了解类型擦除吗? java 注解:深入理解Java注解类型 秒懂,Java 注解 (Annotation)你可以这样学 jav…...

vue2+vue3 HMCXY基础入门
vue2vue3 HMCXY基础入门 一、Vue2.x技术精讲1.Vue快速上手(1)Vue概念(2)创建实例(3)插值表达式(4)响应式特性(5)开发者工具 2.Vue指令二、Vue3.x技术精讲 一、…...

一次线程数超限导致的hive写入hbase作业失败分析
1.集群配置 操作系统:SuSe操作系统 集群节点:100台相同配置的服务器 单台:核心112Core,内存396G 2.问题现象 现象1:跑单个入库任务报错,批量提交任务后出现OOM异常 执行12个hivesql,将数据写入hbase.hbase入库有近一半的任务报错。 每次报错的任务不是同一个,hivesql…...

ip属地是手机号还是手机位置?一文理清
在数字化和网络化的今天,IP属地这一概念逐渐成为了人们关注的焦点。特别是在社交媒体和在线平台上,IP属地的显示往往让人联想到用户的地理位置。然而,关于IP属地到底与手机号还是手机位置有关,却存在着不少误解和混淆。本文将深入…...

查看设备uuid
在大多数操作系统中,可以通过不同的方式来查看设备的 UUID(Universally Unique Identifier)。以下是一些常见的方法: 在Linux系统中,可以使用命令行工具blkid或lsblk来查看设备的 UUID。例如,执行以下命令…...

C_C++输入输出(下)
C_C输入输出(下) 用两次循环的问题: 1.一次循环决定打印几行,一次循环决定打印几项 cin是>> cout是<< 字典序是根据字符在字母表中的顺序来比较和排列字符串的(字典序的大小就是字符串的大小)…...

All in one 的 AI tool Chain “Halomate”
这不算广告啊,就是真好用,虽然是我哥们儿的产品 比如你定了个gpt的plus 订阅,你发现好像有挺多功能 1- chat,这个自不必说,必须的功能 2- 高级语音 现在变成学英语的了,实时视频也就是我过年给姑婶介绍是…...

crewai框架第三方API使用官方RAG工具(pdf,csv,json)
最近在研究调用官方的工具,但官方文档的说明是在是太少了,后来在一个视频里看到了如何配置,记录一下 以PDF RAG Search工具举例,官方文档对于自定义模型的说明如下: 默认情况下,该工具使用 OpenAI 进行嵌…...

脉冲信号傅里叶变换与频域分析:从计算到理解
摘要 本文聚焦于脉冲信号的傅里叶变换,详细推导了矩形脉冲信号和单边指数信号的傅里叶变换过程,深入解释了傅里叶变换结果 F ( ω ) F(\omega) F(ω) 的内涵,包括其定义、物理意义、包含的信息以及在实际应用中的重要性。旨在帮助读者全面掌…...

6.【BUUCTF】[SUCTF 2019]CheckIn
打开题目页面如下 看样子是一道有关文件上传的题 上传一句话木马 显示:非法后缀! 看来.php后缀被过滤了 上传一张带有木马的照片 在文件地址处输入cmd 输入以下代码执行 copy 1.jpg/b4.php/a 5.jpg 最后一行有一句话木马 上传带有木马的图片 但其实…...

基于springboot的体质测试数据分析及可视化设计
作者:学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等 文末获取“源码数据库万字文档PPT”,支持远程部署调试、运行安装。 项目包含: 完整源码数据库功能演示视频万字文档PPT 项目编码࿱…...

孟加拉国_行政边界省市边界arcgis数据shp格式wgs84坐标
这篇内容将深入探讨孟加拉国的行政边界省市边界数据,该数据是以arcgis的shp格式提供的,并采用WGS84坐标系统。ArcGIS是一款广泛应用于地理信息系统(GIS)的专业软件,它允许用户处理、分析和展示地理空间数据。在GIS领域…...

可视化相机pose colmap形式的相机内参外参
目录 内参外参转换 可视化相机pose colmap形式的相机内参外参 内参外参转换 def visualize_cameras(cameras, images):fig plt.figure()ax fig.add_subplot(111, projection3d)for image_id, image_data in images.items():qvec image_data[qvec]tvec image_data[tvec]#…...

数据结构 树2
文章目录 前言 一,二叉搜索树的高度 二,广度优先VS深度优先 三,广度优先的代码实现 四,深度优先代码实现 五,判断是否为二叉搜索树 六,删除一个节点 七,二叉收索树的中序后续节点 总结 …...

GB/T 44721-2024 与 L3 自动驾驶:自动驾驶新时代的基石与指引
1.前言 在智能网联汽车飞速发展的当下,自动驾驶技术成为了行业变革的核心驱动力。从最初的辅助驾驶功能,到如今不断迈向高度自动化的征程,每一步都凝聚着技术的创新与突破。而在这一进程中,标准的制定与完善对于自动驾驶技术的规…...

AURIX TC275学习笔记3 官方例程 (UART LED WDT)
文章目录 参考资料1. ASCLIN_UART_12. GPIO_LED_Button_13. WDT (Watch Dog Timer) 参考资料 AURIX TC275学习笔记1 资料收集Getting Started with AURIX™ Development Studio 官方帮助文档happy hacking for TC275! 硬件平台使用AURIX™ TC275 Lite 套件,按照参…...

Vim的基础命令
移动光标 H(左) J(上) K(下) L(右) $ 表示移动到光标所在行的行尾, ^ 表示移动到光标所在行的行首的第一个非空白字符。 0 表示移动到光标所在行的行首。 W 光标向前跳转一个单词 w光标向前跳转一个单词 B光标向后跳转一个单词 b光标向后跳转一个单词 G 移动光标到…...