Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >SWIG (v1.3.29)生成的C++ to Java Vector类不能正常工作

SWIG (v1.3.29)生成的C++ to Java Vector类不能正常工作
EN

Stack Overflow用户
提问于 2011-11-16 01:40:55
回答 2查看 4.8K关注 0票数 11

我有一些原生C++代码,我正在使用SWIG将它们转换成Java,这样我的Java应用程序就可以使用它们。特别是,有一些函数会返回std::vector。下面是我的接口文件的一个片段:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
%include "std_vector.i"
namespace std {
  %template(Vector) vector<double>;
  %template(Matrix) vector<vector<double> >;
}

%include "std_string.i"

我正在使用的SWIG版本中包含了std_string.istd_vector.i。我的第一个惊喜是,Java输出包括SWIG“自己的”版本的Vector类(而不是使用java.util.Vector)。我真正的问题是从这些函数返回的Vectors似乎不起作用。例如,我不能使用get() (有时会使程序崩溃)或返回负值的size()函数来检索它们的内容。我知道Vector包含数据,因为我编写了相同函数的“字符串”版本,它们只是简单地迭代Vectors (回到原生C++代码中),并返回逗号分隔的String值中的内容。虽然这是一个有效的解决方法,但最终我希望它能正常工作,使我能够接收和操作Vectors。任何帮助/建议都将不胜感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-18 22:49:35

在Java语言中包装std::vector的合适的基类型是java.util.AbstractList。使用java.util.Vector作为基础会很奇怪,因为最终会有两组存储,一组在std::vector中,另一组在java.util.Vector中。

SWIG没有为你做这件事的原因是因为you can't have AbstractList in Java,它必须是AbstractList<Double> (Double继承自Object,而double是一个原始类型)。

说到这里,我用Java语言编写了一个很好地包装了std::vector<double>std::vector<std::vector<double> >的小示例。它并不完整,但它支持Java语言中的"for each“迭代风格和元素上的set()/get()。它应该足以展示如何在你需要的时候实现其他东西。

我将在接下来的部分中讨论接口文件,但基本上都是连续和完整的。

从定义我们的模块numnum.i开始

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
%module num

%{
#include <vector>
#include <stdexcept>

std::vector<double> testVec() {
  return std::vector<double>(10,1.0);
}

std::vector<std::vector<double> > testMat() {
  return std::vector<std::vector<double> >(10, testVec());
}
%}

%pragma(java) jniclasscode=%{
  static {
    try {
        System.loadLibrary("num");
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load. \n" + e);
      System.exit(1);
    }
  }
%}

我们有用于生成的num_wrap.cxx#include和用于测试的两个函数实现(它们可能在一个单独的文件中,我只是出于懒惰/方便的考虑才把它们放在这里的)。

我喜欢在Java SWIG界面中使用的%pragma(java) jniclasscode=也有一个技巧,可以使共享对象/DLL对界面的用户透明地加载。

接口文件中的下一步是我们想要包装的std::vector部分。我不使用std_vector.i,因为我们需要做一些更改:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
namespace std {

    template<class T> class vector {
      public:
        typedef size_t size_type;
        typedef T value_type;
        typedef const value_type& const_reference;
        %rename(size_impl) size;
        vector();
        vector(size_type n);
        size_type size() const;
        size_type capacity() const;
        void reserve(size_type n);
        %rename(isEmpty) empty;
        bool empty() const;
        void clear();
        void push_back(const value_type& x);
        %extend {
            const_reference get_impl(int i) throw (std::out_of_range) {
                // at will throw if needed, swig will handle
                return self->at(i);
            }
            void set_impl(int i, const value_type& val) throw (std::out_of_range) {
                // at can throw
                self->at(i) = val;
            }
        }
    };
}

这里的主要变化是%rename(size_impl) size;,它告诉SWIG将std::vector中的size()暴露为size_impl。我们需要这样做,因为Java希望size返回一个int,而std::vector版本返回的size_type很可能不是int

接下来,在接口文件中,我们告诉它我们想要实现的基类和接口,以及编写一些额外的Java代码来强制类型不兼容的函数之间的事情:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
%typemap(javabase) std::vector<double> "java.util.AbstractList<Double>"
%typemap(javainterface) std::vector<double> "java.util.RandomAccess"
%typemap(javacode) std::vector<double> %{
  public Double get(int idx) {
    return get_impl(idx);
  }
  public int size() {
    return (int)size_impl();
  }
  public Double set(int idx, Double d) {
    Double old = get_impl(idx);
    set_impl(idx, d.doubleValue());
    return old;
  }

%}

%typemap(javabase) std::vector<std::vector<double> > "java.util.AbstractList<Vector>"
%typemap(javainterface) std::vector<std::vector<double> > "java.util.RandomAccess"
%typemap(javacode) std::vector<std::vector<double> > %{
  public Vector get(int idx) {
    return get_impl(idx);
  }
  public int size() {
    return (int)size_impl();
  }
  public Vector set(int idx, Vector v) {
    Vector old = get_impl(idx);
    set_impl(idx, v);
    return old;
  }

%}

这将为std::vector<double>设置一个java.util.AbstractList<Double>基类,为std::vector<std::vector<double> >设置一个java.util.AbstractList<Vector>基类(Vector是我们在接口的Java端称为std::vector<double>的基类)。

我们还在Java端提供了一个getset的实现,它可以处理doubleDouble之间的转换。

最后,我们在界面中添加:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
namespace std {
  %template(Vector) std::vector<double>;
  %template(Matrix) std::vector<vector<double> >;
}

std::vector<double> testVec();
std::vector<std::vector<double> > testMat();

这告诉SWIG将std::vector<double> (具有特定类型)称为Vector,将std::vector<vector<double> >类似地称为Matrix。我们还告诉SWIG公开我们的两个测试函数。

接下来是test.java,这是一个用Java语言编写的简单main,用来测试一下我们的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.AbstractList;

public class test {
  public static void main(String[] argv) {
    Vector v = num.testVec();
    AbstractList<Double> l = v;
    for (Double d: l) {
      System.out.println(d);
    }
    Matrix m = num.testMat();
    m.get(5).set(5, new Double(5.0));
    for (Vector col: m) {
      for (Double d: col) {
        System.out.print(d + " ");
      }
      System.out.println();
    }
  }
}

为了构建和运行它,我们要做的是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
swig -java -c++ num.i
g++ -Wall -Wextra num_wrap.cxx -shared -I/usr/lib/jvm/java-6-sun/include -I/usr/lib/jvm/java-6-sun/include/linux/ -o libnum.so

javac test.java && LD_LIBRARY_PATH=. java test

我在Linux/x86上用g++ V4.4和SWIG 1.3.40进行了测试。

可以在here中找到num.i的完整版本,但始终可以通过将每个部分粘贴到一个文件中来根据此答案进行重建。

我还没有从AbstractList实现的东西

  1. add() -可以通过push_back()实现,std_vector.i甚至尝试在默认情况下实现一些兼容的东西,但它不能解决Doubledouble的问题,也不能匹配AbstractList中指定的返回类型(不要忘记递增modCount)
  2. remove() -在时间复杂性方面对std::vector来说不是很好,但也不是不可能实现)(建议使用另一个CollectionmodCount)
  3. A构造函数也是如此,但这里不实现。可以在set()get()的同一位置实现,但需要$javaclassname来命名生成的构造函数correctly.
  4. You可能希望使用类似this的名称来检查size()中的size_type->int转换是否正常。
票数 16
EN

Stack Overflow用户

发布于 2011-12-07 13:22:53

我是悬赏这个问题的人,因为我也有同样的问题。我有点尴尬地报告,我终于找到了真正的解决方案--它在SWIG手册中!修复方法是在编译生成的代码时使用g++-fno-strict-aliasing标志--就这么简单。我不得不承认,我花了很多时间在谷歌上搜索才最终发现了这一点。

问题是,最近版本的g++做了一些积极的优化,对指针别名做了一些假设,这些假设不适用于SWIG为std_vector (以及其他情况)生成的代码。g++ 4.1不能做到这一点,但4.4.5肯定做到了这一点。这些假设是完全有效的,并被当前的ISO标准所允许,尽管我不确定它们有多广为人知。基本上,两个不同类型的指针(有几个例外)永远不能指向同一个地址。SWIG生成的用于在指向对象的指针和jlong之间进行转换的代码与此规则冲突。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8145605

复制
相关文章
SWIG 官方文档第二部分 - 机翻中文人肉修正
本章简要概述了 C++11 标准的 SWIG 实现。SWIG 的这一部分仍在进行中。
韩伟
2021/09/03
2.3K0
【C++修炼之路】10. vector类
使用STL的三个境界:能用,明理,能扩展 ,那么下面学习vector,我们也是按照这个方法去学习
每天都要进步呀
2023/03/28
4680
【C++修炼之路】10. vector类
C++实现不能被继承的类——终结类
C++如何实现不能被继承的类,即终结类。Java中有final关键字修饰,C#中有sealed关键字修饰,而C++目前还没有类似的关键字来修饰类实现终结类,需编程人员手动实现。但从C++11开始,提出了final关键字来申明终结类。
恋喵大鲤鱼
2018/08/03
1.8K0
vector类
1.vector的介绍和使用 1.vector的介绍 vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为
海盗船长
2020/08/27
7590
vmware workstation 克隆后网卡eth0不能正常工作
解决方法如下 修改/etc/udev/rules.d/70-persistent-net.rules 将eth0这行注释掉或者删除, 这里记载的还是克隆系统时的MAC地址,但是新启动的系统MAC已经更改, 将NAME="eth1" 改为 “eth0”,ATTR 标记的MAC地址,这个是虚拟机为这个虚拟网卡分配的MAC,用上面的MAC替换掉 /etc/sysconfig/network-scripts /ifcfg-eth0中的MAC 然后重启即可 还有一个办法,不用eth0,直接用eth1等,把/etc/sysconfig/network-scripts/ifcfg-eth0复制成/etc/sysconfig/network-scripts/ifcfg-eth1
三杯水Plus
2018/11/14
2.4K0
C++ Vector
c++ vector 简介 vector 是顺序容器的一种,vector 是可变长的动态数组(可存放任意类型),支持随机访问迭代器。所有 STL 算法都能对 vector 进行操作,要使用 vector,需要包含头文件 vector 优点 - 因其拥有一段连续的内存空间,能非常好的支持随即存取,即[]操作符。 - 根据下标随机访问某个元素的时间是常数,在尾部添加一个元素的时间大多情况下也是常数,总体来说速度很快 缺点 - 若要表示的向量长度较长(需要为向量内部保存很多数),容易导致内存泄漏,而且
ruochen
2021/05/20
1.9K0
C++ Vector
Vector类
void addElement(E obj): 将指定的组件添加到此向量的末尾,将其大小增加 1
星哥玩云
2022/09/14
4730
配置SSL证书后,Nginx的HTTPS 不能正常工作的原因有哪些
申请ssl证书,配置nginx支持https与证书,可是访问https的nginx总是出现错误,也导致小程序发https请求失败,这是什么原因呢?
网盾JoySSL小张
2023/08/31
4.9K0
C++ vector
头文件 #include <vector> using namespace std;
ClearSeve
2022/02/11
3370
C++中vector「vector「int」 」
1、定义vector<vector<int>> A;//错误的定义方式vector<vector<int> > A;//正缺的定义方式2、插入元素若想定义A = [[0,1,2],[3,4,5]],则://正确的插入方式vector<vector<int> > A;//A.push_back里必须是vectorvector<int> B;B.push_back(0);B.push_back(1);B.push_back(2);A.push_back(B);B.clear();B.push_back(3);B
狼啸风云
2020/07/15
1.4K0
小朋友学C++(18):标准库vector类
vector(向量)是 C++中的一种数据结构,也是一个类。它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的。 一、定义和初始化 vectorv1; // T为类型名,比如int, float, string等 vectorv2(v1); // 将v1赋值给v2 vectorv3(n,i); // v3中含n个值为i的元素 二、操作 v.empty(); // 判断v是否为空 v.s
海天一树
2018/04/17
4380
java之学习vector类的特有功能
结果示意图 vector类概述 Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector 的大小可以根据需要增大或缩小,以适应创建 Vecto
吾爱乐享
2018/07/12
3810
正常的工作流程
修改文件,将它们更新的内容添加到索引中。 $ git add file1 file2 file3 你现在为commit做好了准备,你可以使用git diff命令再加上–cached参数,看看哪些文件将被提交(commit)。 (如果没有–cached参数,git diff会显示当前你所有已做的但没有加入到索引里的修改。)你也可以使用git status命令来获得当前项目的一个状况。
用户3004328
2018/09/06
7490
python swig 调用C/C++接口
当你觉得python慢的时候,当你的c/c++代码难以用在python上的时候,你可能会注意这篇文章。swig是一个可以把c/c++代码封装为python库的工具。(本文封装为python3的库)
用户5760343
2022/05/13
7540
c++ vector的遍历
vector 是C++标准模板库中的一个类模板。 用vector<typename> v 可以声明一个元素类型为typename的容器类模板v。 v.push_back()函数可以向容器v的尾部添加一
用户6021899
2021/07/05
1K0
C++中的vector
注意:直接赋值的方法容易导致vector下标越界,产生下标越界访问的错误,所以建议使用push_back()方法。
狼啸风云
2023/10/07
2460
[DS]实现Vector类
原文链接:https://blog.csdn.net/humanking7/article/details/80787279
祥知道
2020/03/10
4550
SWIG 官方文档第三部分 - 机翻中文人肉修正
很有可能,您正在阅读本章是出于以下两个原因之一;您要么想自定义 SWIG 的行为,要么无意中听到有人嘟囔着一些关于“typemaps”的难以理解的胡言乱语,然后问自己“typemaps,那些是什么?” 也就是说,让我们先做一个简短的免责声明,即“Typemaps”是一种高级自定义功能,可以直接访问 SWIG 的低级代码生成器。不仅如此,它们还是 SWIG C++ 类型系统(它自己的一个重要主题)的组成部分。typemaps 通常不是使用 SWIG 的必需部分。因此,如果您已经找到了进入本章的方法,并且对 SWIG 默认情况下已经做了什么只有一个模糊的概念,那么您可能需要重新阅读前面的章节。
韩伟
2021/09/03
3.6K0
Python中的SWIG入门
SWIG (Simplified Wrapper and Interface Generator,简化封装和接口生成器) 是一个开源工具,用于将C/C++代码转换为各种高级编程语言的接口代码。它允许开发人员在Python等脚本语言中直接使用底层的C/C++代码,以提高开发效率和灵活性。
大盘鸡拌面
2023/10/17
6220
java类集框架(ArrayList,LinkedList,Vector区别)
主要分三类:集合(set)、列表(List)、映射(Map) 1.集合:没有重复对象,没有特定排序方式 2.列表:对象按索引位置排序,可以有重复对象 3.映射:有一个键对象和一个值对象,键不可重复,值可以重复
用户3030674
2018/09/14
8450

相似问题

JAVA类不能正常工作

11

包装std::vector的std::vector,C++ SWIG Python

12

用swig生成向量到java.util.Vector代码

15

SWIG:生成额外的(手动) Java类

11

如何在java程序中使用SWIG生成的C++类

14
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文