【snmp】net-snmp添加自定义MIB(标量和表格)

2023-11-01 09:40

本文主要是介绍【snmp】net-snmp添加自定义MIB(标量和表格),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

安装net-snmp见:【snmp】centos6.5安装和配置snmp5.7.1

net-snmp添加自定义MIB(标量):【snmp】net-snmp添加自定义MIB(标量) 

net-snmp添加自定义MIB(表格) 见:【snmp】net-snmp添加自定义MIB(表格)

 

一、编写MIB文件

 

复制代码

--
-- MyTest-MIB.my
-- MIB generated by MG-SOFT Visual MIB Builder Version 6.0  Build 88
-- Wednesday, August 05, 2020 at 16:51:00
--MyTest-MIB DEFINITIONS ::= BEGINIMPORTSOBJECT-GROUP            FROM SNMPv2-CONF            enterprises, Integer32, Unsigned32, OBJECT-TYPE, MODULE-IDENTITY            FROM SNMPv2-SMIDisplayString, RowStatus FROM SNMPv2-TC;    -- 1.3.6.1.4.1.2020myModule MODULE-IDENTITY LAST-UPDATED "202008051610Z"        -- August 05, 2020 at 16:10 GMTORGANIZATION "Organization."CONTACT-INFO "Contact-info."DESCRIPTION "Description."::= { enterprises 2020 }--
-- Node definitions
---- 1.3.6.1.4.1.2020.1myOid OBJECT IDENTIFIER ::= { myModule 1 }-- 1.3.6.1.4.1.2020.1.1myScalar OBJECT-TYPESYNTAX DisplayStringMAX-ACCESS read-writeSTATUS currentDESCRIPTION"Description."::= { myOid 1 }-- 1.3.6.1.4.1.2020.1.2myTable OBJECT-TYPESYNTAX SEQUENCE OF MyEntryMAX-ACCESS read-create --修改类型为read-createSTATUS currentDESCRIPTION"Description."::= { myOid 2 }-- 1.3.6.1.4.1.2020.1.2.1myEntry OBJECT-TYPESYNTAX MyEntryMAX-ACCESS read-create --修改类型为read-createSTATUS currentDESCRIPTION"Description."INDEX { myIndex }::= { myTable 1 }MyEntry ::=SEQUENCE { myIndexInteger32,mycol1OCTET STRING,mycol2Integer32,chrsRowStatus --修改类型为RowStatus}-- 1.3.6.1.4.1.2020.1.2.1.1myIndex OBJECT-TYPESYNTAX Integer32 (1..10000)MAX-ACCESS read-only --根据实际业务修改类型STATUS currentDESCRIPTION"Description."::= { myEntry 1 }-- 1.3.6.1.4.1.2020.1.2.1.2mycol1 OBJECT-TYPESYNTAX OCTET STRINGMAX-ACCESS read-writeSTATUS currentDESCRIPTION"Description."::= { myEntry 2 }-- 1.3.6.1.4.1.2020.1.2.1.3mycol2 OBJECT-TYPESYNTAX Integer32MAX-ACCESS read-writeSTATUS currentDESCRIPTION"Description."::= { myEntry 3 }-- 1.3.6.1.4.1.2020.1.2.1.4myrs OBJECT-TYPESYNTAX RowStatus --修改为RowStatusMAX-ACCESS read-createSTATUS currentDESCRIPTION"Description."::= { myEntry 4 }END--
-- MyTest-MIB.my
--

复制代码

 

 

二、使用mib2c命令生成.c和.h文件

2.1使用mib2c.scalar.conf :生成标量对象框架代码

 env MIBS="+/usr/local/snmp/share/snmp/mibs/MyTest-MIB.txt" /usr/local/snmp/bin/mib2c -c mib2c.scalar.conf MyTest-MIB::myOid

以上命令执行完后会生成myOid.h和myOid.c文件

 

2.2使用mib2c.iterate.conf 或 mib2c.mfd.conf :生成表对象框架代码

env MIBS="+/usr/local/snmp/share/snmp/mibs/MyTest-MIB.txt" /usr/local/snmp/bin/mib2c -c mib2c.iterate.conf MyTest-MIB::myModule

以上命令执行完后会生成myModule.h和myModule.c文件

 

三、修改后的C文件

修改后的myOid.c文件内容如下,有中文注释的地方就是修改的地方

复制代码

/** Note: this file originally auto-generated by mib2c using*        $*/#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "myOid.h"/** Initializes the myOid module */
void
init_myOid(void)
{const oid       myScalar_oid[] = { 1, 3, 6, 1, 4, 1, 2020, 1, 1 };DEBUGMSGTL(("myOid", "Initializing\n"));netsnmp_register_scalar(netsnmp_create_handler_registration("myScalar", handle_myScalar, myScalar_oid,OID_LENGTH(myScalar_oid),HANDLER_CAN_RWRITE));
}/**定义一个变量*/
static char buff[256]="";int
handle_myScalar(netsnmp_mib_handler *handler,netsnmp_handler_registration *reginfo,netsnmp_agent_request_info *reqinfo,netsnmp_request_info *requests)
{int             ret;/** We are never called for a GETNEXT if it's registered as a* "instance", as it's "magically" handled for us.  *//** a instance handler also only hands us one request at a time, so* we don't need to loop over a list of requests; we'll only get one. */switch (reqinfo->mode) {case MODE_GET:snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,buff, //定义的变量名称buffstrlen(buff) //buff的长度);break;/** SET REQUEST** multiple states in the transaction.  See:* http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg*/case MODE_SET_RESERVE1:/** or you could use netsnmp_check_vb_type_and_size instead */ret = netsnmp_check_vb_type(requests->requestvb, ASN_OCTET_STR);if (ret != SNMP_ERR_NOERROR) {netsnmp_set_request_error(reqinfo, requests, ret);}break;case MODE_SET_RESERVE2:/** XXX malloc "undo" storage buffer */if ( 0/* XXX if malloc, or whatever, failed: */ ) {netsnmp_set_request_error(reqinfo, requests,SNMP_ERR_RESOURCEUNAVAILABLE);}break;case MODE_SET_FREE:/** XXX: free resources allocated in RESERVE1 and/or* RESERVE2.  Something failed somewhere, and the states* below won't be called. */break;case MODE_SET_ACTION:/** XXX: perform the value change here */if ( 0/* XXX: error? */ ) {netsnmp_set_request_error(reqinfo, requests, 0/* some error */);}break;case MODE_SET_COMMIT:/** XXX: delete temporary storage */memcpy(buff,requests->requestvb->buf,requests->requestvb->val_len); // 赋值buff[requests->requestvb->val_len] ='\0';   //字符串结束符if ( 0/* XXX: error? */ ) {/** try _really_really_ hard to never get to this point */netsnmp_set_request_error(reqinfo, requests,SNMP_ERR_COMMITFAILED);}break;case MODE_SET_UNDO:/** XXX: UNDO and return to previous value for the object */if ( 0/* XXX: error? */ ) {/** try _really_really_ hard to never get to this point */netsnmp_set_request_error(reqinfo, requests,SNMP_ERR_UNDOFAILED);}break;default:/** we should never get here, so this is a really bad error */snmp_log(LOG_ERR, "unknown mode (%d) in handle_myScalar\n",reqinfo->mode);return SNMP_ERR_GENERR;}return SNMP_ERR_NOERROR;
}

复制代码

 

修改后的myModule.c文件内容如下,有中文注释的地方就是修改的地方

复制代码

/** Note: this file originally auto-generated by mib2c using*  $*/#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "myModule.h"/** Initializes the myModule module */
void
init_myModule(void)
{/** here we initialize all the tables we're planning on supporting */initialize_table_myTable();
}//注释掉这一行
//# Determine the first/last column names/** Initialize the myTable table by defining its contents and how it's structured */
void
initialize_table_myTable(void)
{const oid       myTable_oid[] = { 1, 3, 6, 1, 4, 1, 2020, 1, 2 };const size_t    myTable_oid_len = OID_LENGTH(myTable_oid);netsnmp_handler_registration *reg;netsnmp_iterator_info *iinfo;netsnmp_table_registration_info *table_info;DEBUGMSGTL(("myModule:init", "initializing table myTable\n"));reg = netsnmp_create_handler_registration("myTable", myTable_handler,myTable_oid, myTable_oid_len,HANDLER_CAN_RWRITE);table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER,   /* index: myIndex */0);table_info->min_column = COLUMN_MYINDEX;table_info->max_column = COLUMN_MYRS;iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);iinfo->get_first_data_point = myTable_get_first_data_point;iinfo->get_next_data_point = myTable_get_next_data_point;iinfo->table_reginfo = table_info;netsnmp_register_table_iterator(reg, iinfo);netsnmp_inject_handler_before(reg,netsnmp_get_cache_handler(MYTABLE_TIMEOUT, myTable_load,myTable_free, myTable_oid,myTable_oid_len), TABLE_ITERATOR_NAME);/** Initialise the contents of the table here */
}#define NNN 1024 //定义这个宏,下面这个结构体用到/** Typical data structure for a row entry */
struct myTable_entry {/** Index values */long            myIndex;/** Column values *///long            myIndex; // 上面已经定义了char            mycol1[NNN];size_t          mycol1_len;char            old_mycol1[NNN];size_t          old_mycol1_len;long            mycol2;long            old_mycol2;long            myrs;/** Illustrate using a simple linked list */int             valid;struct myTable_entry *next;
};struct myTable_entry *myTable_head;/** create a new row in the (unsorted) table */
struct myTable_entry *
//补全这个函数的参数,其实就是表格中那三列的内容
//这个函数就是添加一行数据的函数,RowStatus列不传也可以,程序内部会自动处理
myTable_createEntry(long myIndex,char *mycol1,size_t mycol1_len,long mycol2)
{struct myTable_entry *entry;entry = SNMP_MALLOC_TYPEDEF(struct myTable_entry);if (!entry)return NULL;entry->myIndex = myIndex;snprintf(entry->mycol1, sizeof(entry->mycol1), "%s", mycol1);     //将mycol1数据赋给结构体entry->mycol1_len = mycol1_len;                                 //将mycol1_len数据赋给结构体entry->mycol2 = mycol2;                                         //将mycol2数据赋给结构体entry->next = myTable_head;myTable_head = entry;return entry;
}/** remove a row from the table */
void
myTable_removeEntry(struct myTable_entry *entry)
{struct myTable_entry *ptr, *prev;if (!entry)return;                 /* Nothing to remove */for (ptr = myTable_head, prev = NULL;ptr != NULL; prev = ptr, ptr = ptr->next) {if (ptr == entry)break;}if (!ptr)return;                 /* Can't find it */if (prev == NULL)myTable_head = ptr->next;elseprev->next = ptr->next;SNMP_FREE(entry);           /* XXX - release any other internal resources */
}#define STRMAX 1024 //定义宏/** Example cache handling - set up linked list from a suitable file */
int
myTable_load(netsnmp_cache * cache, void *vmagic)
{FILE           *fp;struct myTable_entry *this;char            buf[STRMAX];/** The basic load routine template assumes that the data to* be reported is held in a file - with one row of the file* for each row of the table.* If your data is available via a different API, you* should amend this initial block (and the control of the* 'while' loop) accordingly.* 'XXX' marks where the template is incomplete and* code will definitely need to be added. */fp = fopen("/data/for/myTable", "r");if (!fp) {return -1;}while (fgets(buf, STRMAX, fp)) {this = SNMP_MALLOC_TYPEDEF(struct myTable_entry);/** XXX - Unpick 'buf' to extract the individual field values* and then populate the 'this' data structure with them */this->next = myTable_head;myTable_head = this;    /* Iterate helper is fine with unordered lists! */}fclose(fp);return 0;                   /* OK */
}void
myTable_free(netsnmp_cache * cache, void *vmagic)
{struct myTable_entry *this, *that;for (this = myTable_head; this; this = that) {that = this->next;SNMP_FREE(this);        /* XXX - release any other internal resources */}myTable_head = NULL;
}/** Example iterator hook routines - using 'get_next' to do most of the work */
netsnmp_variable_list *
myTable_get_first_data_point(void **my_loop_context,void **my_data_context,netsnmp_variable_list * put_index_data,netsnmp_iterator_info *mydata)
{*my_loop_context = myTable_head;return myTable_get_next_data_point(my_loop_context, my_data_context,put_index_data, mydata);
}netsnmp_variable_list *
myTable_get_next_data_point(void **my_loop_context,void **my_data_context,netsnmp_variable_list * put_index_data,netsnmp_iterator_info *mydata)
{struct myTable_entry *entry =(struct myTable_entry *) *my_loop_context;netsnmp_variable_list *idx = put_index_data;if (entry) {snmp_set_var_typed_integer(idx, ASN_INTEGER, entry->myIndex);idx = idx->next_variable;*my_data_context = (void *) entry;*my_loop_context = (void *) entry->next;return put_index_data;} else {return NULL;}
}/** handles requests for the myTable table */
int
myTable_handler(netsnmp_mib_handler *handler,netsnmp_handler_registration *reginfo,netsnmp_agent_request_info *reqinfo,netsnmp_request_info *requests)
{netsnmp_request_info *request;netsnmp_table_request_info *table_info;struct myTable_entry *table_entry;struct myTable_entry *table_row; //这个变量未定义int ret; //变量未定义DEBUGMSGTL(("myModule:handler", "Processing request (%d)\n",reqinfo->mode));switch (reqinfo->mode) {/** Read-support (also covers GetNext requests)*/case MODE_GET:for (request = requests; request; request = request->next) {table_entry = (struct myTable_entry *)netsnmp_extract_iterator_context(request);table_info = netsnmp_extract_table_info(request);switch (table_info->colnum) {case COLUMN_MYINDEX:if (!table_entry) {netsnmp_set_request_error(reqinfo, request,SNMP_NOSUCHINSTANCE);continue;}snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,table_entry->myIndex);break;case COLUMN_MYCOL1:if (!table_entry) {netsnmp_set_request_error(reqinfo, request,SNMP_NOSUCHINSTANCE);continue;}snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,table_entry->mycol1,table_entry->mycol1_len);break;case COLUMN_MYCOL2:if (!table_entry) {netsnmp_set_request_error(reqinfo, request,SNMP_NOSUCHINSTANCE);continue;}snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,table_entry->mycol2);break;case COLUMN_MYRS:if (!table_entry) {netsnmp_set_request_error(reqinfo, request,SNMP_NOSUCHINSTANCE);continue;}snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,table_entry->myrs);break;default:netsnmp_set_request_error(reqinfo, request,SNMP_NOSUCHOBJECT);break;}}break;/** Write-support*/case MODE_SET_RESERVE1:for (request = requests; request; request = request->next) {table_entry = (struct myTable_entry *)netsnmp_extract_iterator_context(request);table_info = netsnmp_extract_table_info(request);switch (table_info->colnum) {case COLUMN_MYCOL1:/** or possibly 'netsnmp_check_vb_type_and_size' */ret =netsnmp_check_vb_type_and_max_size(request->requestvb,ASN_OCTET_STR,sizeof(table_entry->mycol1));if (ret != SNMP_ERR_NOERROR) {netsnmp_set_request_error(reqinfo, request, ret);return SNMP_ERR_NOERROR;}break;case COLUMN_MYCOL2:/** or possibly 'netsnmp_check_vb_int_range' */ret = netsnmp_check_vb_int(request->requestvb);if (ret != SNMP_ERR_NOERROR) {netsnmp_set_request_error(reqinfo, request, ret);return SNMP_ERR_NOERROR;}break;case COLUMN_MYRS:ret = netsnmp_check_vb_rowstatus(request->requestvb,(table_entry ? RS_ACTIVE :RS_NONEXISTENT));if (ret != SNMP_ERR_NOERROR) {netsnmp_set_request_error(reqinfo, request, ret);return SNMP_ERR_NOERROR;}break;default:netsnmp_set_request_error(reqinfo, request,SNMP_ERR_NOTWRITABLE);return SNMP_ERR_NOERROR;}}break;case MODE_SET_RESERVE2:for (request = requests; request; request = request->next) {table_entry = (struct myTable_entry *)netsnmp_extract_iterator_context(request);table_info = netsnmp_extract_table_info(request);switch (table_info->colnum) {case COLUMN_MYRS:switch (*request->requestvb->val.integer) {case RS_CREATEANDGO:case RS_CREATEANDWAIT:table_row =myTable_createEntry(*table_info->indexes->val.integer,"",0,0);//补全,这里是创建一个新的行if (table_row) {netsnmp_insert_iterator_context(request,table_row);} else {netsnmp_set_request_error(reqinfo, request,SNMP_ERR_RESOURCEUNAVAILABLE);return SNMP_ERR_NOERROR;}}}}break;case MODE_SET_FREE:for (request = requests; request; request = request->next) {table_entry = (struct myTable_entry *)netsnmp_extract_iterator_context(request);table_info = netsnmp_extract_table_info(request);switch (table_info->colnum) {case COLUMN_MYRS:switch (*request->requestvb->val.integer) {case RS_CREATEANDGO:case RS_CREATEANDWAIT:if (table_entry && !table_entry->valid) {myTable_removeEntry(table_row); //多传了table_data参数,删除}}}}break;case MODE_SET_ACTION:for (request = requests; request; request = request->next) {table_entry = (struct myTable_entry *)netsnmp_extract_iterator_context(request);table_info = netsnmp_extract_table_info(request);switch (table_info->colnum) {case COLUMN_MYCOL1:memcpy(table_entry->old_mycol1,table_entry->mycol1, sizeof(table_entry->mycol1));table_entry->old_mycol1_len = table_entry->mycol1_len;memset(table_entry->mycol1, 0,sizeof(table_entry->mycol1));memcpy(table_entry->mycol1,request->requestvb->val.string,request->requestvb->val_len);table_entry->mycol1_len = request->requestvb->val_len;break;case COLUMN_MYCOL2:table_entry->old_mycol2 = table_entry->mycol2;table_entry->mycol2 = *request->requestvb->val.integer;break;}}/** Check the internal consistency of an active row */for (request = requests; request; request = request->next) {table_entry = (struct myTable_entry *)netsnmp_extract_iterator_context(request);table_info = netsnmp_extract_table_info(request);switch (table_info->colnum) {case COLUMN_MYRS:switch (*request->requestvb->val.integer) {case RS_ACTIVE:case RS_CREATEANDGO:if ( 0/* 出错条件 */ ) {netsnmp_set_request_error(reqinfo, request,SNMP_ERR_INCONSISTENTVALUE);return SNMP_ERR_NOERROR;}}}}break;case MODE_SET_UNDO:for (request = requests; request; request = request->next) {table_entry = (struct myTable_entry *)netsnmp_extract_iterator_context(request);table_info = netsnmp_extract_table_info(request);switch (table_info->colnum) {case COLUMN_MYCOL1:memcpy(table_entry->mycol1,table_entry->old_mycol1,sizeof(table_entry->mycol1));memset(table_entry->old_mycol1, 0,sizeof(table_entry->mycol1));table_entry->mycol1_len = table_entry->old_mycol1_len;break;case COLUMN_MYCOL2:table_entry->mycol2 = table_entry->old_mycol2;table_entry->old_mycol2 = 0;break;case COLUMN_MYRS:switch (*request->requestvb->val.integer) {case RS_CREATEANDGO:case RS_CREATEANDWAIT:if (table_entry && !table_entry->valid) {myTable_removeEntry(table_row);//多传了table_data参数,删除}}break;}}break;case MODE_SET_COMMIT:for (request = requests; request; request = request->next) {table_entry = (struct myTable_entry *)netsnmp_extract_iterator_context(request);table_info = netsnmp_extract_table_info(request);switch (table_info->colnum) {case COLUMN_MYRS:switch (*request->requestvb->val.integer) {case RS_CREATEANDGO:table_entry->valid = 1;/** Fall-through */case RS_ACTIVE:table_entry->myrs = RS_ACTIVE;break;case RS_CREATEANDWAIT:table_entry->valid = 1;/** Fall-through */case RS_NOTINSERVICE:table_entry->myrs = RS_NOTINSERVICE;break;case RS_DESTROY:myTable_removeEntry(table_entry);//修改table_row为table_entry,否则删除行不成功,多传了table_data参数,删除}}}break;}return SNMP_ERR_NOERROR;
}

复制代码

 

 

四、载入自定义MIB库

1、在服务器/root/net-snmp-5.7.1/agent/mibgroup/目录下新建一个目录mytest-mib。将生成的myOid.h、myOid.h和修改后的myModule.c 、myModule.c文件放到mytest-mib目录下。

在/root/net-snmp-5.7.1/agent/mibgroup目录下新建文件mytest.h

mytest.h文件内容为:

config_require(mytest-mib/myOid);
config_require(mytest-mib/myModule);

 

2、如果snmp服务在运行,停止snmp服务

 

3、在/root/net-snmp-5.7.1目录下依次执行下面3个命令编译安装

./configure --prefix=/usr/local/snmp --with-mib-modules="mytest"

 make

 make install

 

 

五、测试

1、执行/usr/local/snmp/sbin/snmpd -c /usr/local/snmp/etc/snmpd.conf 命令启动snmp服务

 

测试标量

1、设置myNode的值为"harara"

/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.2020.1.1.0 s harara

2、查看myNode的值

/usr/local/snmp/bin/snmpget -v 2c -c public localhost 1.3.6.1.4.1.2020.1.1.0

 

 测试表格

1、执行/usr/local/snmp/bin/snmpwalk -v 2c -c public localhost 1.3.6.1.4.1.2020.1.2查看表格内容,可以看到表里什么都没有

2、添加第一行数据:/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.2020.1.2.1.4.1 i 4

   这个命令表示对表的第一行的第三列设置值为4,因为第三列为RowStatus类型,所以系统会创建这一行

(表中原本是没有第一行的,只要对第一行的RowStatus列写入4就可以创建这一行)

3、设置字段值, 例:设置第一行数据中的myCol1字段:/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.2020.1.2.1.2.1 s harara

4、删除第1行,对第1行的第4列写入6即可:/usr/local/snmp/bin/snmpset -v 2c -c public localhost 1.3.6.1.4.1.2020.1.2.1.4.1 i 6

 

 

 

参考地址

利用mib2c生成框架代码

 

作者:小念

出处:https://www.cnblogs.com/kiko2014551511/

本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。

这篇关于【snmp】net-snmp添加自定义MIB(标量和表格)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/322105

相关文章

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

SpringBoot 自定义消息转换器使用详解

《SpringBoot自定义消息转换器使用详解》本文详细介绍了SpringBoot消息转换器的知识,并通过案例操作演示了如何进行自定义消息转换器的定制开发和使用,感兴趣的朋友一起看看吧... 目录一、前言二、SpringBoot 内容协商介绍2.1 什么是内容协商2.2 内容协商机制深入理解2.2.1 内容

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

2、PF-Net点云补全

2、PF-Net 点云补全 PF-Net论文链接:PF-Net PF-Net (Point Fractal Network for 3D Point Cloud Completion)是一种专门为三维点云补全设计的深度学习模型。点云补全实际上和图片补全是一个逻辑,都是采用GAN模型的思想来进行补全,在图片补全中,将部分像素点删除并且标记,然后卷积特征提取预测、判别器判别,来训练模型,生成的像

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

Prompt - 将图片的表格转换成Markdown

Prompt - 将图片的表格转换成Markdown 0. 引言1. 提示词2. 原始版本 0. 引言 最近尝试将图片中的表格转换成Markdown格式,需要不断条件和优化提示词。记录一下调整好的提示词,以后在继续优化迭代。 1. 提示词 英文版本: You are an AI assistant tasked with extracting the content of