简体   繁体   English

SWIG 将生成的类从不同的模块和包导入当前类

[英]SWIG Importing generated class from a different module and package into the current class

I'm having difficulty getting the SWIG typemap(javapackage) to work properly.我很难让 SWIG typemap(javapackage)正常工作。 I tried making a simple version of the problem, and even that seems to fail.我尝试制作一个简单版本的问题,即使这样似乎也失败了。

foo.h: foo.h:

#ifndef FOO_H
#define FOO_H

class Foo
{
public:
    Foo() {};
    int doSomething() { return 1 };
};

#endif

bar.h:酒吧.h:

#ifndef BAR_H
#define BAR_H

#include "foo.h"

class Bar
{
public:
    Bar() {};
    int doSomething(Foo foo) { return foo.doSomething(); };
};

#endif

Foo.i Foo.i

%module FooMod

%include "typemaps.i"
%include "stdint.i"

%{
#include "../header/foo.h"
%}

%include "../header/foo.h"

Bar.i酒吧

%module BarMod

%import "Foo.i"

%typemap("javapackage") Foo, Foo *, Foo & "com.me.t.foo";

%include "typemaps.i"
%include "stdint.i"

%{
#include "../header/bar.h"
%}

%include "../header/bar.h"

Running these with this the following commands:使用以下命令运行这些:

swig -c++ -java -package com.me.t.foo -outdir ../../src/com/me/t/foo -o ../src/Foo.cpp Foo.i
swig -c++ -java -package com.me.t.bar -outdir ../../src/com/me/t/bar -o ../src/Bar.cpp Bar.i

And I get this output:我得到这个输出:

package com.me.t.bar;

public class Bar {
  private long swigCPtr;
  protected boolean swigCMemOwn;

  protected Bar(long cPtr, boolean cMemoryOwn) {
    swigCMemOwn = cMemoryOwn;
    swigCPtr = cPtr;
  }

  protected static long getCPtr(Bar obj) {
    return (obj == null) ? 0 : obj.swigCPtr;
  }

  protected void finalize() {
    delete();
  }

  public synchronized void delete() {
    if (swigCPtr != 0) {
      if (swigCMemOwn) {
        swigCMemOwn = false;
        BarModJNI.delete_Bar(swigCPtr);
      }
      swigCPtr = 0;
    }
  }

  public Bar() {
    this(BarModJNI.new_Bar(), true);
  }

  public int doSomething(Foo foo) {
    return BarModJNI.Bar_doSomething(swigCPtr, this, Foo.getCPtr(foo), foo);
  }

}

BarModJNI.java: BarModJNI.java:

package com.me.t.bar;

public class BarModJNI {
  public final static native long new_Bar();
  public final static native int Bar_doSomething(long jarg1, Bar jarg1_, long jarg2, Foo jarg2_);
  public final static native long Bar_getFoo(long jarg1, Bar jarg1_);
  public final static native void delete_Bar(long jarg1);
}

The files are generated properly, but notice that there is no import statement , so Foo can't be found from either of the Bar Java classes.文件生成正确,但请注意没有导入语句,因此无法从 Bar Java 类中找到Foo This is a simple example, but just hard-coding an import statement isn't an option for me since the generated source files containing the C JNI code might have the wrong locations of the "Foo" class files.这是一个简单的示例,但仅对导入语句进行硬编码对我来说不是一种选择,因为生成的包含 C JNI 代码的源文件可能具有错误的“Foo”类文件位置。

This seems like a very simple and common problem, so, what I'm wondering is if I'm missing something or if I'm doing something wrong.这似乎是一个非常简单和常见的问题,所以,我想知道是我遗漏了什么还是我做错了什么。

Thanks for the help!谢谢您的帮助!

Got the same problem and found answer, so posting it for community.遇到了同样的问题并找到了答案,因此将其发布给社区。

You need to make 3 changes.您需要进行 3 次更改。

  1. Add import statements to generated proxy class (Bar.java):将导入语句添加到生成的代理类 (Bar.java):

     // Bar.i %pragma(java) jniclassimports=%{ import com.me.t.foo.Foo; %}
  2. Add import statements to generated JNI wrapper class (BarModJNI.java):将导入语句添加到生成的 JNI 包装类 (BarModJNI.java):

     // Bar.i %typemap(javaimports) Bar %{ import com.me.t.foo.Foo; %}
  3. Tell SWIG to make Foo.getCPtr a public member variable because Bar class will want to access it:告诉 SWIG 将Foo.getCPtr公共成员变量,因为 Bar 类将要访问它:

     // Foo.i SWIG_JAVABODY_PROXY(public, public, SWIGTYPE) SWIG_JAVABODY_TYPEWRAPPER(public, public, public, SWIGTYPE)

Reference:参考:

Just a couple of comments on the answer provided by Zbigniew.只是对 Zbigniew 提供的答案发表一些评论。 I have faced the same problem described in this post.我遇到了这篇文章中描述的同样问题。 I would like to clarify two points.我想澄清两点。

Firstly, it seems to me that step 1 is for adding the import in JNI wrapper class (whateverJNI.java) while step 2 is for adding import to the specific class.首先,在我看来,第 1 步是在 JNI 包装类(无论 JNI.java)中添加导入,而第 2 步是将导入添加到特定类。

Secondly, step 2 is not working for me, instead of %typemap(javaimports) <class> I had to use %typemap(javaimports) SWIGTYPE .其次,第 2 步对我不起作用,而不是%typemap(javaimports) <class>我不得不使用%typemap(javaimports) SWIGTYPE Bad thing is it adds the imports to all the generated java classes and not only to the desired one.不好的是它将导入添加到所有生成的 java 类中,而不仅仅是添加到所需的类中。

Finally, I am still having the problem that SWIG does not recognize the imported class when wrapping the specific type and it still uses SWIGTYPE_<type> instead of directly <type>最后,我仍然遇到问题,即 SWIG 在包装特定类型时无法识别导入的类,它仍然使用SWIGTYPE_<type>而不是直接使用<type>

I have faced the same issue.我遇到了同样的问题。 I solved by writing (You need to write inside .i file)我通过写解决了(你需要写在 .i 文件中)

%typemap(javaimports) namespace::classname
%{
import com.yourcompany.yourapp.*;
%}

This code generates import statement only the class that you have specified.此代码仅生成您指定的类的导入语句。
CAUTION: You must specify the native namespace, otherwise your class will not be seen!注意:您必须指定本机命名空间,否则将看不到您的类!

Example: If your C++ Code would be like this:示例:如果您的 C++ 代码是这样的:

namespace A{  
class MyPerfectClass{

};  
}

You need to write你需要写

%typemap(javaimports) A::MyPerfectClass
%{
import com.yourcompany.yourapp.*;
%}

If you want to add this import statement to all java wrapped classes, you need to write如果你想把这个import语句添加到所有java包装的类中,你需要写

%typemap(javaimports) SWIGTYPE
%{
import com.yourcompany.yourapp.*;
%}

For JNI Java Class:对于 JNI Java 类:

%pragma(java) jniclassimports=%{
import com.yourcompany.yourapp.*;
%}

The proof code is here:证明代码在这里:

package com.mycompany.myproject.A_package;

import com.mycompany.myproject.B_package.*;

public class MYCLASS{
  private transient long swigCPtr;
  protected transient boolean swigCMemOwn;

  public MYCLASS(long cPtr, boolean cMemoryOwn) {
    swigCMemOwn = cMemoryOwn;
    swigCPtr = cPtr;
  }

  public static long getCPtr(MYCLASSobj) {
    return (obj == null) ? 0 : obj.swigCPtr;
  }
  .
  . etc.

If you have more than one class, you can continue like:如果你有不止一门课,你可以继续这样:

%typemap(javaimports) A::MyPerfectClass , A::B::MyFantasticClass , MyNoNamespaceClass 

I've tested with SWIG 4.0 and it works.我已经使用 SWIG 4.0 进行了测试,并且可以正常工作。
I've changed package and class names on proof code because I cannot share my company and class name.我更改了证明代码上的包名和类名,因为我无法共享我的公司和类名。 I hope this answer would be helpful for others who will have the same issue.我希望这个答案对有同样问题的其他人有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM