Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling C++ exceptions in Java via SWIG

Tags:

java

c++

swig

I'm attempting to use SWIG to wrap a C++ class into a Java class. This C++ class has a method that throws an exception.

I have three goals, none of which are currently happening although I have followed the manual as I understand it:

  • To get the Java class to declare throws <exceptiontype> on the method that throws in C++
  • To get the SWIG generated Exception class to extend java.lang.Exception
  • To override Exception.getMessage() in the generated SWIG class.

It seems that the root of the problem seems that my typemaps are not being applied, as none of the above happens. What have I done wrong?

Minimal example is below. The C++ does not have to compile, I'm only interested in the generated Java. The class of the exception is irrelevant, and the code below uses IOException just because the documentation uses it. All code is adapted from examples here:

  • http://www.swig.org/Doc1.3/Java.html#typemap_attributes
  • http://www.swig.org/Doc1.3/Java.html#exception_typemap

C++ header file (test.h):

#include <string>

class CustomException {
private:
  std::string message;
public:
  CustomException(const std::string& message) : message(msg) {}
  ~CustomException() {}
  std::string what() {
    return message;
  }
};

class Test {
public:
  Test() {}
  ~Test() {}
  void something() throw(CustomException) {};
};

SWIG .i file:

%module TestModule
%{
#include "test.h"
%}

%include "std_string.i" // for std::string typemaps
%include "test.h"

// Allow C++ exceptions to be handled in Java
%typemap(throws, throws="java.io.IOException") CustomException {
  jclass excep = jenv->FindClass("java/io/IOException");
  if (excep)
    jenv->ThrowNew(excep, $1.what());
  return $null;
}

// Force the CustomException Java class to extend java.lang.Exception
%typemap(javabase) CustomException "java.lang.Exception";

// Override getMessage()
%typemap(javacode) CustomException %{
  public String getMessage() {
    return what();
  }
%}

When running this with swig -c++ -verbose -java test.i with SWIG 2.0.4, the exception class does not extend java.lang.Exception and none of the Java methods have a throws declaration.

like image 886
Martin Foot Avatar asked Dec 21 '12 16:12

Martin Foot


1 Answers

You're going to kick yourself when you see this. A fixed version of your SWIG interface is:

%module TestModule
%{
#include "test.h"
%}

%include "std_string.i" // for std::string typemaps

// Allow C++ exceptions to be handled in Java
%typemap(throws, throws="java.io.IOException") CustomException {
  jclass excep = jenv->FindClass("java/io/IOException");
  if (excep)
    jenv->ThrowNew(excep, $1.what());
  return $null;
}

// Force the CustomException Java class to extend java.lang.Exception
%typemap(javabase) CustomException "java.lang.Exception";

// Override getMessage()
%typemap(javacode) CustomException %{
  public String getMessage() {
    return what();
  }
%}

%include "test.h"

I.e. %include "test.h" comes after the typemaps you wish to apply to the classes in test.h, not before. The typemaps need to have been seen by SWIG at the time the classes they apply to are first seen.

like image 79
Flexo Avatar answered Oct 19 '22 05:10

Flexo