• [技术干货] list的简单介绍和模拟实现-转载
     1.list的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 list和forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。 与其他序列式容器相比(array,vector,deque),list通常在任意位置插入,移除元素的执行效率更好。 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问 2.list的使用 2.1.list的构造 构造函数    接口说明 list(size_type n,const value_type& val = value_type())    构造的list中包含n个值为val的元素 list    构造空的list list(const list& x)    拷贝构造函数 list(InputIterator first,InputIterator last)    用[first,last)区间中的元素构造list 2.2.list iterator的使用 函数声明    接口说明 begin + end    返回第一个元素的迭代器+返回最后一个元素的下一个位置的迭代器 rbegin + rend    返回最后一个数据的位置迭代器+返回第一个数据的前一个位置的迭代器 2.3.list capacity 函数声明    接口说明 empty    检测list是否为空,是返回true,不是返回false size    返回list节点中有效节点的个数 2.4.list element access 函数声明    接口说明 front    返回list的第一个节点中值的引用 back    返回list的最后一个节点中值的引用 2.5.list modifiers 函数声明    接口说明 push_front    在list首元素前插入值为list的元素 pop_front    删除list中的第一个元素 push_back    在list尾部插入值为val的元素 pop_back    删除list的最后一个元素 insert    在list position位置插入值为val的元素 erase    删除list position位置的元素 swap    交换两个list中的元素 clear    清空list中的有效元素 3.list的迭代器失效 我们可以类似先把迭代器暂时理解成指针。则迭代器失效即迭代器所指向的节点无效。即该节点被删除了。因为list的底层结构为带头节点的双向循环链表,因此在list中进行插入不会导致list迭代器失效的,只有在删除时才会失效,并且失效的只是指向删除节点的迭代器,其他迭代器不会受到影响。  4.list和vector的对比 list和vector都是STL中非常重要的序列式容器,由于两个容器的底层结构不一样,导致其特性以及应用场景不同  vector    list 底层结构    动态顺序表,一段连续空间    带头节点的双向循环链表 随机访问    支持随机访问,访问某个元素的效率O(1)    不支持随机访问,访问某个元素的效率O(N) 插入和删除    任意位置插入和删除效率低,需要移动元素,时间复杂度为O(N),插入时有可能需要增容,增容:开辟新空间,拷贝元素,释放旧空间,导致效率更低    任意位置插入和删除效率高,不需要移动元素,时间复杂度为O(1) 空间利用率    底层为连续空间,不容易造成内存碎片,空间利用率高,缓存利用率高    底层节点动态开辟,小节点容易造成内存碎片,空间利用率低,缓存利用率低 迭代器    原生态指针    对原生态指针进行封装 迭代器失效    在插入元素时,要给所有的迭代器重新赋值,因为插入元素有可能导致重新扩容,导致原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效    插入元素不会导致迭代器失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响 使用场景    需要高效存储,支持随机访问,不关心插入和删除    大量的插入和删除,不关心随机访问 5.list的模拟实现 #define  _CRT_SECURE_NO_WARNINGS  #include <iostream> #include <algorithm> #include <assert.h> using namespace std;  namespace smk {     //一个一个的节点     template <class T>     struct ListNode     {         ListNode* next;         ListNode* prev;         T data;          ListNode(const T& x)             :next(nullptr)             ,prev(nullptr)             ,data(x)         {}     };      //封装 + 运算符重载     template <class T,class Ref,class Ptr>     struct list_iterator     {         typedef ListNode<T> Node;         typedef list_iterator<T ,Ref,Ptr> Self;          list_iterator(Node* p)             :_pNode(p)         {}         Ref operator*()         {             return _pNode->data;         }          //找到节点的指针         Self& operator++()         {             _pNode = _pNode->next;             return *this;         }          Self& operator--()         {             _pNode = _pNode->prev;             return *this;         }         bool operator!=(const Self& it)         {             return _pNode != it._pNode;         }          bool operator==(const Self& it)         {             return _pNode == it._pNode;         }          Ptr operator->()         {             return &_pNode->data;         }         //节点的指针         Node* _pNode;     };          //带头双向循环链表     template <class T>     class list     {         typedef ListNode<T> Node;     public:         typedef list_iterator<T,T&,T*> iterator;         typedef list_iterator<T, const T&,const T*> const_iterator;          iterator begin()         {             return iterator(_head->next);         }         const_iterator begin() const         {             return const_iterator(_head->next);         }         iterator end()         {             return iterator(_head);         }         const_iterator end() const         {             return const_iterator(_head);         }          void Initialize()         {             _head = new Node(T());             _head->next = _head;             _head->prev = _head;              _size = 0;         }          list()         {             Initialize();         }          template <class Interiterator>         list(Interiterator first, Interiterator last)         {             Initialize();             while (first != last)             {                 push_back(*first);                 ++first;             }         }          void swap(list<T>& st)         {             std::swap(_head, st._head);             std::swap(_size, st._size);         }          //现代写法的拷贝构造         list(const list<T>& st)         {             Initialize();             list<T> tmp(st.begin(), st.end());             swap(tmp);         }          //拷贝构造         /*list(const list<T>& st)         {             Initialize();              for (auto& e : st)             {                 push_back(e);             }         }*/          list<T>& operator=(list<T> st)         {             swap(st);             return *this;         }          //传统写法的赋值重载         /*list<int>& operator=(const list<T>& st)         {             if (this != &st)             {                 clear();                 for (auto& e : st)                 {                     push_back(e);                 }             }              return *this;         }*/          void clear()         {             iterator it = begin();             while (it != end())             {                 it = erase(it);             }         }          ~list()         {             clear();              delete _head;             _head = nullptr;         }          size_t size() const         {             return _size;         }          bool empty() const         {             return _size == 0;         }          void push_back(const T& val)         {             //Node* newNode = new Node(val);             //Node* tail = _head->prev;             _head  tail  newNode             //tail->next = newNode;             //newNode->prev = tail;             //newNode->next = _head;             //_head->prev = newNode;              insert(end(),val);         }          void push_front(const T& val)         {             insert(begin(), val);         }          void pop_front()         {             erase(begin());         }          void pop_back()         {             erase(--end());         }          iterator insert(iterator pos, const T& val)         {             Node* newnode = new Node(val);             Node* cur = pos._pNode;             Node* prev = cur->prev;             //链接 prev newnode cur             prev->next = newnode;             newnode->prev = prev;             newnode->next = cur;             cur->prev = newnode;              ++_size;              return iterator(newnode);         }          iterator erase(iterator pos)         {             assert(pos._pNode != _head);             Node* prev = pos._pNode->prev;             Node* next = pos._pNode->next;              prev->next = next;             next->prev = prev;              --_size;              return iterator(next);         }     private:         //链表的指针         Node* _head;          size_t _size;     };  ———————————————— 版权声明:本文为CSDN博主「孙梦康」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/SASCII/article/details/128315305 
  • [问题求助] c#在win7调用ccgateway的https任意接口报错
    【问题来源】【必填】浙公院【问题简要】【必填】c#在win7调用ccgateway的https任意接口报错,SSL通道无法创建。调用AgentClient-20210419005736.jar包8443端口的https接口是正常的。排查发现请求端必须是tls1.2版本,但现在win7系统的Schannel套件默认不开启该版本,希望ccgateway的tls版本能支持,非互联网应用。【问题类别】【必填】CTI平台提供的cc-gateway接口【AICC解决方案版本】【必填】AICC 8.15.0 CC-Gateway开发指南 (RESTful)【问题现象描述】【必填】调用jar包和ccgateway不同结果参考如下图,调用ccgateway的8043端口出错,调用agentclient.jar包的返回数据正常​​
  • [C/C++] 一起来看看auto推导规则
    🎄auto推导规则1️⃣如果auto声明的变量是按值初始化,则推导出的类型会忽略const、volatile限定符。进一步解释为,在使用auto声明变量时,既没有使用引用,也没有使用指针,那么编译器在推导的时候会忽略const和volatile限定符。当然auto本身也支持添加const、volatile限定const int i = 10; auto j = i; // auto推导类型为int auto &m = i; // auto推导类型为const int& auto *k = i; // auto推导类型为const int const auto n = j; // auto推导类型为int✨✨解释:因为在进行类型推导时忽略了const、volatile,所以i虽然我const int类型结果却是int类型 而m和k分别为引用和指针初始化,所以原本的const和volatile属性得以保留 最后,const auto结合让n的类型推导为const int2️⃣在使用auto声明变量初始化时,目标对象如果是引用&,则引用属性会被忽略:int i = 10; int &j = i; auto m = j; // auto推导类型为int✨✨解释:虽然j是i的引用,j的类型为int&但是在推导m的时候auto会直接忽略掉其中的引用推导为int类型,也就是说明对谁的引用就会直接推导成谁本身的类型3️⃣使用auto和万能引用声明变量时,对于左值会将auto推导为引用类型:int i = 10; auto&& k = i; // auto推导类型为int& auto&& j = 10; // auto推导类型为int解释: 因为i是一个左值,所以k的类型会被推导为int&,auto被推导为int&,这其中用到了引用折叠的规则。而5是一个右值,因此j的类型被推导为int&&,auto被推导为int4️⃣使用auto声明变量,如果目标对象是一个数组或者函数,则auto会被推导为对应的指针类型int i[10]; auto m = i; // auto推导类型为int* int add(int A, int A){ return A+A; } auto j = add // auto推导类型为int (__cdecl *)(int,int)解释: i[10]是数组类型,但是在推导时变为int*,m化为指针类型指向i的首地址,同样,j也退为函数指针类型5️⃣当auto关键字与列表初始化组合时直接使用列表初始化,列表中必须为单元素,否则无法编译,auto类型被推导为单元素的类型。用等号加列表初始化,列表中可以包含单个或者多个元素,auto类型被推导为**std::initializer_list**,其中T是元素类型。请注意,在列表中包含多个元素的时候,元素的类型必须相同,否则编译器会报错。auto A1 = { 10, 12 }; // x1类型为 std::initializer_list auto A2 = { 10, 12.0 }; // 编译失败,花括号中元素类型不同 auto A3{ 10, 12 }; // 编译失败,不是单个元素 auto A4 = { 13 }; // x4类型为std::initializer_list auto A5{ 13 }; // x5类型为int
  • [C/C++] 一起来看看重新定义的auto关键字
    ✨一起来看看重新定义的auto关键字🎁auto作为一个在c++98标准就已经开始存在的关键字,因为现在我们已经几乎不再去使用去声明自动变量,于是乎在c++11中我们重新对其进行定义赋予了它新的含义:🎄声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。🎈例如:auto A = 1;这里没有对A去声明类型,但是通过auto进行推导时已经将A推导为int类型的变量🎈再以字符为例:auto str="hello world";在这里同样是auto自动进行推导,推导类型为 const char*🎈再以函数返回值为例:auto add(int A,int B)->int{return A+B;}再这里add函数声明采用了函数返回类型后置的方法,在这里同样可以看出返回值A+B为int型推导出的函数类型为int型✨但是我们在使用auto时一定要注意,在进行类型推导时一定要对变量进行初始化,比如下面没有初始化就不能编译通过auto A;A=1;✨这里很明显没有进行初始化,也就导致了编译器无法推导具体类型而报错除此之外auto在进行编译推导时还有以下4点规则1️⃣当我们使用auto声明多个变量时,编译器遵循从左往右的推导规则,以最左边的表达式推断auto的具体类型:auto n=12,m=10;在上面的代码因为是以左边的表达式类型推导auto的具体类型,n=12可以推导出为int型,于是m这个时候同样也被声明成int类型,在这种情况下,要注意声明多个变量时要保证声明的变量都是相同的,比如下面的变量类型不同就编译不通过;auto n=12,m=10.0;在这种情况下由于n为int型,m为浮点型,前后不同所以报错2️⃣当使用条件表达式初始化auto声明的变量时要注意,编译器往往会初始化为表达能力更强的类型而并不是是我们想的条件表达式的返回类型,例如:auto A=true?10:12.0;在上面的代码种,虽然条件表达式的返回类型为int但是A的类型依然会被推导为double3️⃣在C++11中静态成员变量是可以用auto声明并且初始化的,不过前提是auto必须使用const限定符: 例如:struct nametype { static const auto A = 12; };一旦使用const就将导致变量的常量化,为了解决这一问题,在c++17中就已经提出了响应的解决方法,代码如下:struct nametype{ static inline auto A=12; }4️⃣无法在形参列表中使用auto声明形参void sum(auto A,auto B){ ...... }
  • [C/C++] 内联命名空间的定义和使用
    内联命名空间的定义和使用✨✨在进行大型开发过程中,我们偶尔发现会遇到函数重名或者类型同名造成的编译冲突问题。为了解决类似的问题,我们需要合理使用命名空间,于是我们可以将函数和类型纳入命名空间中,这样,因为不在同一命名空间下就不会产生函数和类型的冲突比如:namespace name1 { void foo() {} } namespace name2 { void foo() {} } using namespace name1; int main(){ stu(); name2::stu(); }✨✨在上面的例子中我们用有俩个命名空间name1、name2,在两块空间下都具有相同的函数stu()于是我们可以使用命名空间的名称去调用空间内的函数,也可以去通过using关键字去打开命名空间,但是在每次使用空间都需要打开空间就显得有些复杂了,于是在c++11中就增强了命名空间的特性;✨✨在c++11中提出了内联空间的概念,我们可以使用inline关键字将空间内的函数和类型导出在父空间中,这样内联空间内的函数就可以直接通过父空间直接调用,则样就是即使不指定子命名空间也可以使用其子命名空间内的函数和类型了例如:#include #include namespace Parent { namespace name1 { void stu() { std::cout << "命名空间1.0" << std::endl; } } inline namespace name2 { void stu() { std::cout << "命名空间2.0" << std::endl; } } } int main(){ Parent::name1::stu(); Parent::stu(); }✨✨在上面的代码中在对name2使用了inline关键字标记为内联命名空间,所以调用name1的stu函数需要明确指定所属的命名空间。而在调用name2当中的stu函数就显得十分方便了,可以直接通过父空间进行调用但是这一点好像目前看来并没有太大的作用,那么内联命名空间的作用到底是上面呢?其实内联函数命名空间的这一特性在版本的迭代方面就可以看出作用,给大家举个例子看看当我们在进行版本迭代的时候,就比如下面的这段代码#include #inculde namespace Parent { void stu() { std::cout << "版本1.0" << std::endl; } } int main(){ Parent::stu(); }✨✨在对这段代码进行的时候我们就需要对这代代码进行大量的删改操作,但是问题来了,当我们想要再次体验老版本时候就很难再找回原来的版本,那么我们就可以通过内联命名命名空间这样一个特性进行新老版本的更迭比如下面这段代码:namespace Parent { namespace name1 { void stu() { std::cout << "版本1.0" << std::endl; } } inline namespace name2 { void stu() { std::cout << "版本2.0" << std::endl; } } } int main(){ Parent::stu(); }✨✨从上面的代码中可以看出,当我们需要将版本升级到2.0时只需要在将Parent::stu()改为Parent::name2::stu()。我们就可以使用新的版本,不光如此我们也可以在同一个父空间下创建版本3.0、版本4.0、版本5.0,我们只需要创建对应的内联命名空间就好;🎃🎃值得注意的是在同一个父命名空间下只允许一个内联命名空间,不然编译时就会因为不知道使用那个内联命名空间而报错🎃🎃
  • [互动交流] 桌面应用自动化获取C#的DataGridView元素内文本
    请问,想要获取到DataGridView表格内的所有内容,是否存在一次性获取表格内所有内容的方式,由于是数据是动态的所以无法去循环遍历表格内每一个单元格的内容,还请各位大佬们支支招,万般感谢!!!
  • [技术干货] C#使用lambda合并列表中列表【转载】
    今天的做C#项目时,突然要对list列表的列表进行合并汇总,哈哈,写linq和lambda不多,试过几个方法都不行.具体代码如下就是对List<Coio> list中的列表ReportItems进行合并!一般情况下,如果是两个list列表,直接是union即可,但是现在List中的列表呢.当然用最简单的方法就遍历这个list,然后对列表进行AddRange即可,如下代码var list = new List<Coio>();for (int i = 0; i < 10; i++){list.Add(new Coio());}var listItem = new List<ReportItem>();foreach (var item in list){listItem.AddRange(item.ReportItems);}方法自然是没问题了,但就是想有没有更简单的.其实你想到的,微软也想到了.用SelectMany方法即可: var listResult = list.SelectMany(n => n.ReportItems).ToList();看看是不是原来四五行代码,现在就一行代码就解决了~转载自https://www.home1024.com/article/union-a-list-of-lists.html
  • [互动交流] C# 创建Bucket报错 签名不匹配
    The request signature we calculated does not match the signature you provided. Check your key and signing method.
  • [热门活动] C#、TypeScript 之父 Anders Hejlsberg:“会用 Excel 的,都是程序员 ”[转载]
    原文链接:https://thenewstack.io/microsofts-programming-language-czar-anders-hejlsberg-the-interview/                 https://blog.csdn.net/m0_66023967/article/details/123068356?spm=1000.2115.3001.5927Anders Hejlsberg是世界上最重要的计算机程序员之一。作为Turbo Pascal、Delphi、C#和TypeScript等编程语言的创造者,在构建微软.NET等开发环境方面极具影响力,Hejlsberg影响了数以百万计的软件开发人员。近日,Hejlsberg与TNS新闻编辑Darryl K.Taft进行了一场线上对话,围绕微软低代码/无代码、Web3等话题,分享了他对许多与软件开发相关的事情的看法。Excel是一种低代码/无代码工具问:您对于低代码,无代码有什么看法?Anders Hejlsberg:我认为这个领域的潜力巨大。我们常会忽略,其实我们已经拥有了世界上最好的编程语言之一,或许这取决于你如何定义Excel中编程语言。可以说Excel是一种低代码/无代码的程序编写方式,人们运行程序,而他们使用的电子表格就是程序。你可以做一些事情,输入一些东西,然后运行程序,程序会在电子表格的底层运行,并且给出结果。所以我认为挑战其实一直在于这些工具。当达到低代码环境的极限时,你需要找到设置合适的逃生舱口的方法,才不会陷入困境。而且这个逃生舱口,可以转移到一个更完整或完整的编程环境,这意味着有意义的可扩展性模型是必须的。因此,我们需要思考的事情还有很多,但这些事情往往不是最重要的,因为人们往往会转而关注绘制方框和线条,以及这些示例的演示效果。但我常常很好奇,这些工具是否能适应现实世界?很多都不能,但有些可以。这是有趣的地方。问:我的意思是,整体的主旨是努力让更多人进入开发的世界。其中一部分人想要走的更远,成为专业人士,或者至少更加熟练。Anders Hejlsberg:是的。如果你去问所有的Excel用户,他们都不会自称程序员。但是,从某种意义上来说,他们是。问:没错,我比较喜欢把这比作“Blue Apron”和“HelloFresh”这样的套餐服务——它们会让你开始学习烹饪,并且自己动手,做得更好。你认为在软件开发中下一个要克服的挑战是什么?Anders Hejlsberg:在我们写代码的方式和机器学习的可能够帮助我们的方式之间,仍然有非常大的差距。因为我们的大脑以及神经网络的工作方式,从来没有真正关于0和1以及绝对正确的答案,而都是统计和模糊逻辑。然而,所有的编程语言都牢固地扎根于逻辑和可证明性等等。这两种世界观之间存在着巨大的差距。看看我们最终如何弥合这一差距的(如果说我们最终做到了的话)。软件开发中的安全性问:下面我们来谈谈安全问题。在软件开发中,安全性和整个shift left的作用有多重要?Anders Hejlsberg:这取决于你在堆栈中的位置。对于编程语言来说,安全性非常重要,起码这对我的工作影响很大。甚至可以说类型检查器是一种安全形式。这是软件中可利用的漏洞。所以从这个意义上来说,编程语言间接地考虑了安全性。创造可以分析代码,并且指出可能存在的安全漏洞的工具,是我们看待安全性的其他方式。但很显然,这是个现实问题。我是说,世界各地也有人每天上班,他们的工作就是黑入西方国家的公司,从而获得薪水。这细思极恐。有很多人靠滥用科技谋生。虽然这一点令人难过,但这就是现实。Web3的开发问:您对Web3有什么看法?您认为是否需要新的工具进行Web3的开发呢?Anders Hejlsberg:首先,我们要对Web3的概念达成共识,因为人们对此总是各持己见。我喜欢奖励创造者概念,以及创造数字资产并获得奖励的能力。但是,在这个领域也有很多骗子、挂羊头卖狗肉的人和急功近利的人。而且还会造成大量的环境污染,虽然可以将其归因于一些正在进行的采矿活动和能源的使用,所以这是一个多样的世界。我们将看到这一切的结果。因此,我喜欢它的某些部分,也反对它的某些部分。潜力巨大的项目:GitHub构建的Copilot问:我知道您在微软需要做的事情很多,但在微软以外,有没有什么很棒的项目或者工作吸引您的关注?Anders Hejlsberg:我认为微软肯定有一些非常有趣的项目。比如开发者工具、人工智能、机器学习,还有很多其他有意思的事。不知道你是否了解GitHub正在构建的Copilot的项目,能够在世界上所有的开源代码上训练一个机器学习网络,然后让它给出答案,是不是很棒?当然,这仍然有点像西大荒,因为有各种机遇和不可掌控的发展,以及知识产权的未解决的问题,但它展现出巨大的潜力。所以我认为这很吸引人,我正在密切关注这个问题。问:我认为这是2021年的最好的编程项目,涉及到相当大的领域。Anders Hejlsberg:是的,这个项目确实很吸引人。尤其是作为一名程序员,它在很大程度上让人洞察到我们谈论的是什么样的智能。从某种意义上说,用智能这个词有点不恰当,因为如果有人以前写过这段代码,这种机器学习模型的聚合内存可能是正确的,这值得我们注意。它可以在其内存中找到那段代码。但是,如果以前没有人写过,它必须要思考解决方案,结果可能出人意料,所以在这方面还有很多需要思考的地方。但这是一个了不起的工具,因为它把再利用的概念提升到了一个新的水平,让我们不用重复做别人已经做过的事。
  • [问题求助] c#实例 连接不上
    c#实例 连接不上不上
  • [互动交流] C# OBS net45 SDK 上传文件或者下载文件 报错 基础连接已经关闭: 发送时发生错误,请指教
    基础连接已经关闭: 发送时发生错误。
  • C#WebApi同一个接口同一个会话会调用多次,如何判断是否是会话重复请求
    C#WebApi同一个接口同一个会话会调用多次,如何判断是否是会话重复请求
  • [其他语言] C#类的应用系统如何做鲲鹏适配?
    很多企业都用了C#开发语言来开发。这种情况怎么做适配?鲲鹏不是不支持c#吗?该怎么整?
  • [其他语言] c#函数式编程
    #化鲲为鹏,我有话说#从学习编程开始,就只知道面向对象编程,什么java,c++,老师也都苦口婆心的将面向对象的重要性。固然,面向对象,让学习编程更加简单,因为我们只需要知道一个实例调用哪些方法就行了。但也是因为这样,我们对程序运行过程中的数据变化,状态变化,都很模糊或者不关心。如果使用函数式编程,就不一样了。有兴趣的可以了解一下,可以帮助我们写出优雅简洁的代码。比如c#中的linq。
  • [技术干货] 用IKVMC将jar转成dll供c#工程调用【转】
    (转自 https://developer.huawei.com/ict/forum/forum.php?mod=viewthread&tid=24703&highlight  )前言IKVM.NET是一个针对Mono和微软.net框架的java实现,其设计目的是在.NET平台上运行java程序。有些在java程序上可以实现的功能,但在C#中无法实现或者目前不知道怎么实现时(如带有特殊Padding的RSA2048加密,https双向认证等),可以考虑使用IKVM工具把已生成的jar转成dll供C#程序去调用。IKVM官网地址:https://www.nuget.org/packages/IKVM/由于IKVM7最高只支持jdk1.6编译出来的jar转换,建议使用最新版本IKVM8。使用说明前提条件:已通过java实现所需功能,且编译成一个jar,如MyHttpClient.jar。1. 在官网下载ikvm压缩包,这里用的是ikvmbin-8.1.5717.0.zip,解压到一个文件夹中,如C:\tools\ikvm-8.1.5717.0。2. 配置环境变量:在系统环境变量中增加IKVM_HOME:C:\tools\ikvm-8.1.5717.0,同时Path中增加%IKVM_HOME%/bin;3. 把MyHttpClient.jar放到一个工作目录下,如C:\tools\ikvm,在命令行中进入该目录,执行 ikvmc -target:library MyHttpClient.jar,即在当前目录下生产MyHttpClient.dll,这里只需要生成一个dll,如需生产可执行程序,可执行命令 ikvmc -target:exe xxx.jar。4. 在C#工程中引用MyHttpClient.dll以及IKVM相关的dll(C:\tools\ikvm-8.1.5717.0\bin目录下的以IKVM.开头的dll,这里为了方便全部引用了),C#中类的命名空间和java中的类的包名是一致的,如java中import com.huawei.myhttpclient,C#中为using com.huawei.myhttpclient特别注意:由于实际的java实现工程很多情况下都依赖一些第三方jar,比如举例的MyHttpClient工程使用了Apache httpClient相关组件实现的设置客户端,服务端证书,发送消息功能,依赖的jar有:commons-codec-1.9.jar,commons-logging-1.2.jar,httpclient-4.5.2.jar,httpcore-4.4.4.jar,httpmime-4.5.2.jar,在网上查询很多做法是把这些第三方jar依次编译成dll,执行ikvm命令时需要指定指定依赖的dll,比较麻烦,这里的做法是把这些jar用winrar等解压软件打开,然后里面的根目录文件夹org(里面包含了Apache httpClient编译生成的class),拷到MyHttpClient.jar中。补充:最近发现有人使用该方式,执行ikvmc编译命令时,命令行中报错:Class "org.apache.http.impl.client.DefaultHttpClient" not found.可能原因是导出jar时,Options选项中未勾选 Add Directory entries
总条数:30 到第
上滑加载中