ACE编程

ACE对串口编程的支持 ACE对串口编程有支持。主要是这样的几个类ACE_DEV* 和ACE_TTY*。具体的例子可以参看ACE_ROOT/examples/IPC_SAP/DEV_SAP。这个帖子等我慢慢的完善首先介绍一下Serial_Params(串口参数)int baudrate 波特率int xonlim在XON字符被发送之前,输入缓冲区的最小字节int xofflim在XOFF字符被发送之前,输入缓冲区的最大字 阅读详情

ACE历时20年,耗费数千万美金,在中间件领域享有盛誉。更可贵的是,ACE彻底的开源,且没有任何限制条件,完全是共产主义的精神,让人钦佩。

ACE的Wrapper Facade模式解决了夸平台的c++编程问题。虽然我们现在有标准C++,但是目前的C++标准库对于多线程、网络通信、并发处理、进程管理以及小内存分配、共享内存、内存映射文件等诸多实际运用中的问题没有支持。相信随着时间的推移,C++标准库会越来越多的关心我们程序员实际编程中的问题,但是现在,我需要ACE.

ACE的文档在http://www.dre.vanderbilt.edu/Doxygen/Stable/ace/index.html

,你可以从www.riverace.com下载最新的ACE安装包。

UBuntu7.10下安装ACE开发环境

首先要确保UBuntu已经安装了g++和openssl。
apt-get install g++来安装g++
通过新立得软件查找libssl来安装。我安装的是libssl0.9.8,libssl0.9.8-dbg,libssl-dev。
然 后将ACE压缩包解压,并放到自己的目录下,仔细阅读install.html中关于unix的部分,按照上面的做,我没有使用传统方式。如果执行 configure命令或者make命令时报错,通常是缺少相应的库。安装指定的库以后,一定要重新执行../configure命令。
目录/build/ace/.libs下的libACE-5.6.so文件就是我们的动态库文件。

 

使用ACE编写第一个程序

代码编写需要了解ACE的一些基本知识,所有的ace头文件都在ace目录下,我的机器上ace目录安装在/software/ACE_wrappers。

下面的代码并不复杂,主要是编译参数要注意:

g++ -I$ACE_ROOT -L$ACE_ROOT/ace test.cpp -lACE

-l后面指定头文件目录/software/ACE_wrappers

-L后面指定ACE库文件路径/software/ACE_wrappers/ace

-l后面指定库文件名称ACE

 

 

为了确保动态连接库运行时加载正确,需要如下设置:

Fedora7的配置方法--在动态库的配置文件子目录(/etc/ld.so.conf.d)里增加一个文件ace.conf

内容为:/software/ACE_wrappers/ace 这是动态链接库的目录路径,执行ldconfig命令修改全局缓冲文件

 

如果别的linux系统没有/etc/ld.so.conf.d目录,就需要直接将/software/ACE_wrappers/ace加到/etc/ld.so.conf文件中,然后执行ldconfig命令

 

 

 

 

#include "ace/Log_Msg.h"

#include "ace/OS_main.h"

#include "ace/INET_Addr.h"

#include "ace/SOCK_Connector.h"

#include "ace/SOCK_Stream.h"

 

int ACE_TMAIN(int argc, ACE_TCHAR* argv[])

{

ACE_DEBUG((LM_DEBUG,ACE_TEXT("freebird./n")));

ACE_SOCK_Connector connector;

ACE_SOCK_Stream peer;

ACE_INET_Addr peer_addr;

 

if(peer_addr.set(80,"192.168.22.26")==-1)

return 1;

else if(connector.connect(peer,peer_addr)==-1)

return 1;

}

 

用ACE开发网络通信程序

该程序将演示如何将一个简单结构序列化后发送到网络上,如何从网络上接收到数据后反序列化回结构。

ACE的C++ WRAPPER FACADE层将网络通信分成三种角色:连接者(ACE_SOCK_Connector)、等待者(ACE_SOCK_Acceptor)和传输者(ACE_SOCK_Stream)。

 

建立连接

首先使用ACE_SOCK_Connector::connect连接某个服务器(使用ip地址和端口号),该服务器上使用ACE_SOCK_Acceptor::accept等待外部的连接请求。

ACE_INET_Addr类进行管理SOCKET通信使用的IP地址和端口号。

当连接建立的时候,连接者和等待者都初始化一个传输者用于通信。

下面就是连接者如何连接本机的7777端口的服务程序代码:

 

#include <iostream>

using namespace std;

#include "ace/INET_Addr.h"

#include "ace/SOCK_Stream.h"

#include "ace/SOCK_Connector.h"

int main(void)

{

ACE_INET_Addr address("127.0.0.1:7777");

ACE_SOCK_Connector connector;

ACE_SOCK_Stream stream;

if(connector.connect(stream,address)==-1)

{

cout<<strerror(errno)<<endl;

}

}

如果连接成功,connect方法返回0,如果连接失败,返回-1,线程专有的errno变量将被设置对应的错误码,你可以通过strerror函数获取错误信息描述字符串。ACE不使用异常报错,原因之一是早些时候异常并不被所有的C++编译器支持,原因之二是异常对性能仍然有影响,作为高性能底层库ACE仍然采用了C风格进行错误处理。但是你仍然可以在自己的应用逻辑中使用异常,并不会和ACE发生冲突。

下面是等待者的示例:

#include <iostream>

using namespace std;

#include "ace/INET_Addr.h"

#include "ace/SOCK_Stream.h"

#include "ace/SOCK_Acceptor.h"

int main(void)

{

ACE_SOCK_Acceptor acceptor;

//本地端口7777的ACE_INET_Addr对象

ACE_INET_Addr address;

address.set(7777);

//绑定本地端口,并且设置为监听状态

if(acceptor.open(address)==-1)

{

cout<<strerror(errno)<<endl;

}

ACE_SOCK_Stream stream;

if(acceptor.accept(stream)==-1)

{

cout<<strerror(errno)<<endl;

}

}

 

注意,ACE_SOCK_Acceptor::accept和ACE_SOCK_Connector::connect方法都可以接收一个ACE_TIME_Value*参数。该参数缺省直为NULL,就像上面的两个示例,表示除非建立连接,否则不会返回;如果我们创建ACE_TIME_Value time(0,0)对象作为参数,则表示方法不会阻塞,如果不能立刻建立连接,就返回-1,并且errno为EWOULDBLOCK;如果我们创建ACE_TIME_Value time(5,0)对象作为参数,就表示方法会最多等待5秒钟,如果5秒钟内还没有建立连接,就返回-1,并且errno为ETIME.

ACE_SOCK_Acceptor对象没有状态,因此多线程可以在不锁定的情况下共享该对象。

数据传输

通常数据传输的过程是将对象中的数据按照某种格式序列化成连续的字节流,然后发送到网络上,当另一端接收到字节流后,按照此格式反序列化成对象。

当连接建立好后,通信双方都有两个可以发送和接收数据的ACE_SOCK_Stream对象。该对象提供了发送和接收的方法。send_n/recv_n用于发送和接收确定数量的字节流,如果没有发送或者接收完,该方法将阻塞。而send/recv就不保证这一点,可能实际发送或者接收的数据比参数指定的少,该方法不会阻塞,而是返回实际发送或者接收的数据大小。send/recv方法实际是从父类ACE_SOCK_IO继承而来的。

网络传输的一种高效的方法是集中写和分散读。不同缓冲区的数据没有必要拷贝到一起,就可以直接按照次序一次型的发送出去。从网络另一端收到后,有可以分散的写到不同的缓冲区中。这就避免了数据复制的开销。ACE_SOCK_Stream的方法recvv_n/sendv_n方法就提供了这个机制。我们后面的示例将严实这个方法的使用。

如果我们使用TCP/IP协议发送数据,TCP/IP协议有一个Nagle算法。该算法将缓存小数据,减少网络发送的次数,从而避免过多通信的开销。在某些情况下,我们需要关闭该算法,让我们的数据能够立刻发送出去。ACE_SOCK_Stream的set_option方法使用参数TCP_NODELAY可以关闭这个算法。另一个方法是当我们使用sendv_n方法时,也会强制数据立刻发送。

下面的示例将一个结构SHMRecord初始化,并序列化到ACE_OutputCDR对象中。然后使用sendv_n方法将数据发出。

 

#include <iostream>

using namespace std;

#include "ace/INET_Addr.h"

#include "ace/SOCK_Stream.h"

#include "ace/SOCK_Connector.h"

#include "ace/CDR_Stream.h"

 

class SHMRecord

{

public:

SHMRecord():pData_(NULL){}

 

ACE_UINT16 type_;

ACE_UINT32 offset_;

void* pData_;

ACE_UINT32 dataLength_;

 

size_t size() const

{

return 2+4+4+dataLength_;

}

 

~SHMRecord()

{

if(pData_!=NULL)

delete[] static_cast<char*>(pData_);

}

};

 

int operator<<(ACE_OutputCDR & cdr,SHMRecord const& record)

{

cdr<<record.type_;

cdr<<record.offset_;

cdr<<record.dataLength_;

cdr.write_char_array(static_cast<char*>(record.pData_),record.dataLength_);

return cdr.good_bit();

}

 

int operator>>(ACE_InputCDR & cdr,SHMRecord & record)

{

cdr>>record.type_;

cdr>>record.offset_;

cdr>>record.dataLength_;

record.pData_=new char[record.dataLength_]();

cdr.read_char_array(static_cast<char*>(record.pData_),record.dataLength_);

return cdr.good_bit();

}

 

 

 

int main(void)

{

ACE_INET_Addr address("127.0.0.1:7777");

ACE_SOCK_Connector connector;

ACE_SOCK_Stream stream;

if(connector.connect(stream,address)==-1)

{

cout<<strerror(errno)<<endl;

}

 

SHMRecord record;

record.type_=1;

record.offset_=2;

record.pData_=new char[4]();

record.dataLength_=4;

strcpy(static_cast<char*>(record.pData_),"hih");

 

const size_t size=record.size()+ACE_CDR::MAX_ALIGNMENT;

ACE_OutputCDR payload(size);

payload<<record;

 

//create cdr header for this data

ACE_OutputCDR header(ACE_CDR::MAX_ALIGNMENT+8);

header<<ACE_OutputCDR::from_boolean(ACE_CDR_BYTE_ORDER);

header<<ACE_CDR::ULong(size);

 

iovec iov[2];

iov[0].iov_base=header.begin()->rd_ptr();

iov[0].iov_len=8;

iov[1].iov_base=payload.begin()->rd_ptr();

iov[1].iov_len=size;

 

stream.sendv_n(iov,2);

cout<<record.type_<<endl;

cout<<record.offset_<<endl;

cout<<static_cast<char*>(record.pData_)<<endl;

cout<<record.dataLength_<<endl;

}

ACE提供了ACE_OutputCDR和ACE_InputCDR类,是针对网络程序经常遇到的将对象数据序列化到字节流和从字节流中反序列化到对象的情况。你可以提供自己的operator<<和operator>>操作,就像上面的例子一样。

这种方式和支持标准C++流的方式是一样的。那么,为什么不直接使用标准C++流呢?因为ACE所支持的平台很多,有些编译器不支持标准C++流。并且据我个人的体验,标准C++流在内存管理上是封装的,你不可能通过公有方法获得内部关里的缓冲区的指针,除非自己定义自己的派生类,这并不容易。还有一个原因是不同编译器和不同的硬件使用了不同的字节对齐方式(大尾数法和小尾数法)。使用ACE的cdr类就可以保证各种环境下都能使用,因为它在内部使用了CORBA公共数据表示的格式。

对于基本的数值类型,各个平台也有可能有长度的差异,比如int究竟是16,32还是64。所以这里使用了ACE提供的基本数值类型,比如ACE_UINT32。

在这个示例程序里,我们实际上创建了两个ACE_OutputCDR对象,一个用来表示数据头,一个存发实际结构中的数据。数据头中前4个字节存放了一个布尔值,表示本机的字节顺序,后面四个字节表示第二个对象的实际长度。

因此,接收数据时首先接收固定长度的头对象,取得字节顺序标志后,调整字节顺序,然后获取实际长度,根据该长度接收第二个ACE_OutputCDR对象存放的实际数据。

下面的例子演示了如何接收发送来的数据。

 

 

int main(void)

{

ACE_SOCK_Acceptor acceptor;

ACE_INET_Addr address;

address.set(7777);

if(acceptor.open(address)==-1)

{

cout<<strerror(errno)<<endl;

}

ACE_SOCK_Stream stream;

if(acceptor.accept(stream)==-1)

{

cout<<strerror(errno)<<endl;

}

 

 

auto_ptr<ACE_Message_Block>

spBlock(new ACE_Message_Block(ACE_DEFAULT_CDR_BUFSIZE));

ACE_CDR::mb_align(spBlock.get());

if(stream.recv_n(spBlock->wr_ptr(),8)==8)//receive the header of CDR

{

//parse the cdr header

spBlock->wr_ptr(8);

ACE_InputCDR cdr(spBlock.get());

ACE_CDR::Boolean byte_order;

cdr>>ACE_InputCDR::to_boolean(byte_order);

cdr.reset_byte_order(byte_order);

ACE_CDR::ULong length;

cdr>>length;

 

//receive the data from master

spBlock->size(length+8+ACE_CDR::MAX_ALIGNMENT);

if(stream.recv_n(spBlock->wr_ptr(),length)==length)

{

spBlock->wr_ptr(length);

//必须重新创建一个CDR对象,否则解析不正确

ACE_InputCDR cdr2(spBlock.get());

ACE_CDR::Boolean byte_order;

cdr2>>ACE_InputCDR::to_boolean(byte_order);

cdr2.reset_byte_order(byte_order);

ACE_CDR::ULong length;

cdr2>>length;

 

auto_ptr<SHMRecord> spRecord(new SHMRecord);

cdr2>>*spRecord;

cout<<spRecord->type_<<endl;

cout<<spRecord->offset_<<endl;

cout<<static_cast<char*>(spRecord->pData_)<<endl;

cout<<spRecord->dataLength_<<endl;

}

}

}

 

ACE_Message_Block类用来管理数据,内部有一个指向ACE_Data_Block对象的指针,ACE_Data_Block类管理实际的缓冲区数据。这种设计允许多个ACE_Message_Block对象共享同一个ACE_Data_Block对象,对于效率的提高很有帮助。多个ACE_Message_Block对象可以组成一个链表(双向或者单向)。

在上面的例子中,我们 创建了一个默认大小的ACE_Message_Block对象,然后将接收的数据写入ACE_Data_Block的缓冲区中,并且移动写指针的位置。ACE_InputCDR通过和ACE_Message_Block对象关联来读取缓冲区的数据。

 

内存映射文件

多个操作系统平台都提供了内存映射文件,这是一个简单的将数据结构保存到文件中的机制。同时由于32位操作系统的进程虚拟内存最大只能4GB,用内存映射文件的方式就可以突破这个限制,可以用来打开超过4GB的大文件。

而且,内存映射文件其实就是一种共享内存机制,进程间可以通过共享内存直接访问数据。

ACE提供了ACE_MMAP_Memory_Pool类,该类代表了为内存映射文件分配内存的内存池。和ACE_Malloc模板类配合,我们就可以以平台无关的方式操纵内存映射文件了。比如:ACE_Malloc<ACE_MMAP_Memory_Pool,ACE_SYNCH_MUTEX> 。第二个参数是并发锁的策略类。

下面的例子实现了write函数,该函数负责将结构SHMRecord的数据写到内存映射文件snapshot中,并且以HashMap的方式保存。key是offset的字符串表示,value是结构的指针。

注意,结构中的pData_成员指向的内存也应该由ACE_Malloc在内存映射文件中分配。这种模式下,千万用常规思路管理内存回收,比如智能指针,有时候内存不需要回收。

#include <iostream>

#include <sstream>

using namespace std;

#include "ace/MMAP_Memory_Pool.h"

#include "ace/Malloc_T.h"

 

 

 

class SHMRecord

{

public:

SHMRecord():pData_(NULL){}

 

ACE_UINT16 type_;

ACE_UINT32 offset_;

void* pData_;

ACE_UINT32 dataLength_;

 

size_t size() const

{

return 2+4+4+dataLength_;

}

 

};

 

 

typedef

ACE_Malloc<ACE_MMAP_Memory_Pool,ACE_SYNCH_MUTEX> MAllocator;

 

void write()

{

MAllocator allocator("/opt/ace/freebird/snapshot");

 

void * pMemory=allocator.malloc(sizeof(SHMRecord));

if(pMemory==NULL)

{

cout<<"malloc failed"<<endl;

return;

}

SHMRecord* pRecord=new(pMemory) SHMRecord();

pRecord->type_=9;

pRecord->offset_=2;

pRecord->dataLength_=4;

pRecord->pData_=allocator.malloc(4);

ACE_OS::strcpy(static_cast<char*>(pRecord->pData_),"hel");

 

stringstream stream;

stream<<pRecord->offset_;

if(allocator.bind(stream.str().c_str(),pRecord)==-1)

{

cout<<"bind failed"<<endl;

return;

}

 

allocator.sync();

}

 

void read()

{

}

 

int main(void)

{

write();

read();

return 0;

}

 

ACE_Malloc模板类的malloc成员负责分配内存,free负责释放内存,bind负责将数据添加到HashMap中,sync负责将数据从内存写到文件中。构造函数接收文件名作为参数。

现在我们来完成read函数,该函数将负责从内存映射文件中读取数据,并且显示出来。

void read()

{

MAllocator allocator("/opt/ace/freebird/snapshot");

 

ACE_Malloc_LIFO_Iterator<ACE_MMAP_Memory_Pool,ACE_SYNCH_MUTEX> iter(allocator);

 

for(void* pData=0;iter.next(pData)!=0;iter.advance())

{

SHMRecord* pRecord=ACE_reinterpret_cast(SHMRecord*,pData);

cout<<pRecord->type_<<endl;

cout<<pRecord->offset_<<endl;

cout<<static_cast<char*>(pRecord->pData_)<<endl;

cout<<pRecord->dataLength_<<endl;

}

}

这里使用了一个后进先出的迭代器,可以遍历HashMap中的数据。当然也可以使用find方法查找指定的数据。

多个进程因而可以使用同一块共享内存,但是问题是这些内存在每个进程中的基地址可能不同。虽然大多数操作系统能够保证,但是万一遇到意外情况怎么办?在这种情况下直接保存的指针将毫无意义。

 

 

ACE提供了解决方案:

1)使用ACE_Malloc_T<ACE_MMAP_MEMORY_POOL,

ACE_NUll_Mutex,ACE_PI_Control_Block>代替前面的分配器。关键在于ACE_PI_Control_Block类,该类使我们获得了于位置无关的分配内存功能。

2)在我们的结构中使用了普通的C++指针,现在要替换成ACE_Based_Pointer_Basic<char>类型。 该类会针对不同的基地址重新计算指针。

3)迭代器也应该使用父类:

ACE_Malloc_LIFO_Iterator_T<ACE_MMAP_Memory_Pool,ACE_SYNCH_MUTEX,ACE_PI_Control_Block> iter(allocator);

 

线程管理

ACE Wrapper Facade层提供了ACE_Thread_Manager类,该类可以创建和管理线程的生存期、同步和属性。

ACE_Thread_Manger类实现了singletom模式,因此我们需要通过instance函数来创建或者获取对象。spawn方法用来创建一个新的线程,我们需要传递线程函数和函数的参数给该方法。示例如下:

class SnapShotReqWaiter

{

public:

struct Thread_Args

{

Thread_Args(SnapShotReqWaiter* lsp):this_(lsp)

{

}

SnapShotReqWaiter* this_;

};

.....

void run()//throw std::runtime_error

{

Thread_Args* thread_args=new Thread_Args(this);

if(ACE_Thread_Manager::instance()->spawn(run_svc,

ACE_static_cast(void*,thread_args),

THR_DETACHED|THR_SCOPE_SYSTEM,

&threadID_)==-1)

{

throw

std::runtime_error("can't create a new thread in SnapShotReqWiater::run method");

}

 

}

 

static void* run_svc(void* arg)

{

 

}

ACE 5.4.1网络编程框架实战详解 ACE(Adaptive Communication Environment)是一个面向对象的、开放源码的框架,广泛应用于高性能和实时通信服务程序的开发。它提供了丰富的网络通信和并发处理的组件,使得开发此类应用程序变得更加高效和简洁。ACE框架封装了底层的网络编程细节,为开发者提供了高级抽象,大大降低了编写复杂网络应用的难度。TCP/IP协议族,是互联网的基础,它定义了如何在主机和网络之间进行数据交换。 阅读详情

相关推荐

libACE.so.5.8.2(64)

libACE.so.5.8.2(64)

Linux环境使用ACE编辑器,linux下ACE的编译和使用&my项目的编译

$ACE_ROOT/include/makeinclude/platform_macros.GNUln -s(后面的把myseelite2/include/platform_macros.GNU"拷贝到"/usr/local/ACE_wrappers/include/make_include/其实和这个操作的目的是一样的……)直接进入ACE_wrappers目录;mkdir objdircd od...

weixin_39740737的博客 394

ACE库(linux)

ACE库 Linux

gcc/g++ 编译、链接与常用命令工具(1)

参见:https://blog.youkuaiyun.com/surgewong/article/details/39236707

mijichui2153的博客 6452

ACE学习资料(含VC下配置)

全套ACE学习资料!!! 包括VC下配置过程,源代码,ACE程序员指南,ACE程序员教程

ACE在Linux下编译安装.txt

ACE在Linux下编译安装.txt 学习ACE

ACE的安装和使用

ACE Beginner: http://www.cppblog.com/sandy/archive/2005/11/24/1281.html ACE 示例1 --- Time Server:http://www.cppblog.com/sandy/archive/2006/02/16/3293.html ACE 示例2 --- Echo Serverhttp://www.cppbl

C++ 爱好者 make_it_simple888 5406

S32K1XX调试--快速定位HardFault

1、背景 程序运行,发现程序跑飞到HardFault,但不清楚为什么会跑到HardFault中断处理函数去。 2、分析 要想知道为什么会跑到HardFault_Handler中去,就很有必要了解一下,程序上一条执行的是那条命令。 根据汇编指令可以定位上条指令,但如果对汇编指令不是很了解的话,那就很头疼了 根据单步运行也能实现定位,但如果程序量很大,又很杂,可能花费的时间就比较久些。 3、问题查找 提供一种不需要懂汇编指令的查找方法,方法如下: 在中断处理函数中插入以下代码,以及另外定义

ping_devil的博客 4019

ACE下串口编程

ACE下串口编程首先看下相关的类,在ACE下使用非常简单,后面是ACE自带的一个列子。/** * @class ACE_TTY_IO * * @brief Class definitions for platform specific TTY features. * * This class represents an example interface for a specific

胜利者的经验并不复杂,那就是寻找人生的关键点,并在关键时刻竭尽全力 2664

用Python玩转Milvus:从安装SDK到完成第一个向量搜索Demo

本文为Python开发者提供了一份详细的Milvus向量数据库实战指南。文章重点讲解了如何规避版本兼容性陷阱,正确部署Milvus服务端并安装匹配的Python SDK。通过一个电影推荐系统的完整案例,演示了从数据建模、集合创建、向量插入、索引构建到执行混合搜索的全流程,帮助开发者快速上手并完成第一个向量搜索Demo。

weixin_29239279的博客 192

6层高速PCB设计实战:BGA布局与阻抗匹配关键解析

本文深入解析6层高速PCB设计中BGA布局与阻抗匹配的关键技术。通过实战经验分享,详细介绍了六层PCB层叠结构的选择与优化、BGA器件布局技巧、阻抗匹配的实战经验以及高速布线技巧,帮助工程师提升PCB设计水平,确保信号完整性和电源完整性。

weixin_28481133的博客 368

ACE实例编程1

#include "ace/INET_Addr.h"#include "ace/SOCK_Connector.h"#include "ace/SOCK_Stream.h" #include using namespace std; int ACE_TMAIN (int argc, ACE_TCHAR* argv[]) {  const char *pathn

tomhsh的专栏 2338

使用abagen工具箱获取基于脑区的基因表达矩阵

脑区模板定义了您感兴趣的脑区的空间位置。abagen提供了一些预定义的脑区模板,您可以选择使用,也可以使用自定义的脑区模板。它提供了一种简便的方式来获取基于脑区的基因表达矩阵。abagen需要使用Allen脑图谱数据来获取基因表达矩阵。您可以使用abagen内置的下载功能来获取这些数据。这就是使用abagen工具箱获取基于脑区的基因表达矩阵的详细步骤。通过按照上述步骤操作,您可以轻松获取并使用Allen脑图谱数据中的基因表达信息。一旦您加载了脑区模板,您可以使用abagen来获取基于脑区的基因表达矩阵。

web_bug407的博客 1326

ACE编程小结

 1、多线程中的ACE_Reactor::EventLoop,当在多线程(池)中调用EventLoop时,需要注意,在Acceptor/EventHandler中要使用其中的方法Reactor()来获取ACE_Reactor的指针,不要使用ACE_Reactor::instance,道理很简单哟。不过,一定要注意,在编程时,使用Reactor()类方法,比使用单件的方法要好很多,起码安全,也不会破

mjp_mjp的专栏 1738

基于matlab的阈值分割的车牌定位识别系统

车牌自动识别模块是现代社会智能交通系统(ITS)的重要组成部分,是图像处理和模式识别技术研究的热点,具有非常广泛的应用。车牌识别主要包括以下三个主要步骤:车牌区域定位、车牌字符分割、车牌字符识别。本案例通过对采集的车牌图像进行灰度变换、边缘检测、腐蚀及平滑等过程进行车牌图像预处理,并由此得到一种基于车牌颜色纹理特征的车牌定位方法,最终实现了车牌区域定位。车牌字符分割是为了方便后续对车牌字符进行匹配,从而对车牌进行识别。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 968

ASProxy64.dll导致jetbrains家的IDE都无法打开。

摘要:在Windows11系统中,JetBrains IDE无法启动,报错指向ASProxy64.dll文件。该第三方DLL被注入到JVM原生层,导致内存访问冲突(错误代码0xc0000005)。经排查发现此文件来自Astrill软件。解决方案为卸载Astrill后重启电脑,问题得以解决。该案例表明第三方DLL注入可能影响IDE正常运行,卸载相关软件是最直接的解决方法。(149字)

猿小白的博客 936

ACE的Socket网络编程

<br />针对Socket API不直接支持“主动连接”模式,ACE将“连接管理”所涉及的三个角色:<br />主动连接角色(active connection role)<br />被动连接角色(passive connnection role)<br />通信角色(communication role)<br />分别以类的形式提供给使用者以降低复杂度:<br />ACE_SOCK_Connector<br />ACE_SOCK_Connector类是一个工厂(factory),用来主动建立一信的通信

飘羽随风 2443

7.26华为OD机试真题 新系统 - 炸弹人的雷区数量 (Java/Py/C/C++/Js/Go)

7.26华为OD机试真题 新系统 - 炸弹人的雷区数量 (Java/Py/C/C++/Js/Go)

算法大师! 793

ACE网络编程

ACE对程序员的要求比较高,需要了解C++、设计模式、POSA、网络、并发等。 参考书单: 1、 《C++网络编程:运用ACE和模式消除复杂性 卷1》(简称:C++NPv1) 2、 《C++网络编程:基于ACE和框架的系统化复用 卷2》(简称:C++NPv2) 3、 《ACE程序员指南:网络与系统编程的使用设计模式》(简称:APG) 4、 《面向模式的软件架构:网络与并发模式 卷

fighting 765

102、栅极驱动芯片选型与设计

文章摘要 本文分享了栅极驱动芯片选型与设计的实战经验。通过一次因驱动芯片选型不当导致的炸管事故,作者总结了栅极驱动芯片选型的五个关键参数:峰值驱动电流、驱动电压范围、传播延迟匹配、欠压锁定和隔离等级。文章详细分析了自举电路设计中的常见陷阱,以及栅极电阻对开关特性的影响,并强调了PCB布局布线的重要性。最后,作者提供了七条实用建议,包括避免通用型驱动芯片、关注CMTI参数、使用插件电阻等。核心观点是:栅极驱动设计需要综合考虑参数匹配、电路布局和实际调试,示波器实测波形是验证设计的唯一标准。

2401_88858637的博客 44

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

ACE网络编程模式比较

ACE网络编程模式比较 2009-10-10 09:52:50 标签:ACE   [推送到技术圈] ACE将网络编程进行了模式化,以便你不必每次都重复相同的代码。网络编程需要处理的事情多括中断,并发,多线程等,程序格式相对固定,但是健壮的网络程序则相对复杂。为了处理这些情形,ACE内建了几个网络编程

testing2007的专栏 1万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

ACE中网络通讯编程基本架构

 ACE中网络通讯编程基本架构   ACE_Addr是所有ACE"地址"类的基类;如TCP/IP和UDP/IP的地址信息是用ACE_INET_Addr来表示的方法说明ACE_INET_ADDr(),Set() 通过主机名、IP地址和端口号初始化ACE_INET_ADDrstring_to_addr()               将字符串转换为ACE_INET_Addraddr_to_string

787

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

ACE程序演示 ACE中网络通讯编程基本架构

ACE中网络通讯编程基本架构 http://www.21tx.com 2009年01月21日 vckbase walkspeed   ACE_INET_Addr类,包装了网络地址   ACE_SOCK_Connector类,扮演主动连接角色,发起通讯连接。连接到远端的服务。   ACE_SOCK_Acceptor类,扮演被动连接角色,等待连接。等待远端客户的请求。   ACE_SO

nokianasty的专栏 728
上一篇: iconv库的使用
下一篇: offset 宏
inter999
博客等级 码龄19年 18粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值