a %downcast macro for Java needs the name of the JVM wrapper type for a call to jenv->FindClass

Alessio M <[email protected]> Tue, 10 Jun 2025 20:35:14 +0100
Newsgroups gmane.comp.programming.swig
Message-ID <CAL_VXbahgZZPfgf6ouxQyZ5-S_GLX0q19OA+R86XfoAJQe=Vww@mail.gmail.com>
--===============3830934274467218281==
Content-Type: multipart/alternative; boundary="000000000000ea598406373ccd52"

--000000000000ea598406373ccd52
Content-Type: text/plain; charset="UTF-8"

For a given C++ type being wrapped, is it possible to get the
(fully qualified) name of the wrapped type in the target language?

I have many factory methods that return std::shared_ptr<const BaseClass>
I do wrap and export to java several types derived from BaseClass
And I need the runtime wrapper JVM managed type to accurately match those
derived types
I wrote the below %downcast macro
I have a version of this for python which works quite nicely. It uses
$descriptor(DeriverType) to create the python native extension type

But JNI code does not seem to have any descriptor infrastructure in the
module.

Is there a way to make this work in Java?

Thank you for any help you can provide



// Helper function for %downcast, to be called for each target type

%define %_downcast_const(Type)
    {
      auto const out = %dynptrcast(const Type,ptr);
      if (out)
      {
        auto const clazz = jenv->FindClass(  >>>>>
I_NEED_THE_JAVA_CLASS_NAME_HERE<<<<  );
        if (clazz)
        {
          auto const mid = jenv->GetMethodID(clazz, "<init>", "(JZ)V");
          if (mid)
            return reinterpret_cast<jlong>(jenv->NewObject(clazz, mid,
reinterpret_cast<jlong>(new %ptr(const Type)(out)), false));
        }
      }
    }
%enddef



// the actual %downcast macro

%define %downcast(typemaptarget, Types...)

%fragment(%fragment_name(downcast, typemaptarget), "header") {
jlong downcast(%ptr(const typemaptarget) const& ptr, JNIEnv *jenv)
{
  if (!ptr)
    return 0; // TODO: check this is correct
  else
  {
    %formacro(%_downcast_const, Types)
  }
  return 0;
}
}

%typemap(jni) %ptr(typemaptarget) "jobject"
%typemap(jtype) %ptr(typemaptarget) #typemaptarget
%typemap(jstype) %ptr(typemaptarget) #typemaptarget
%typemap(javaout) %ptr(typemaptarget) {
  return $jnicall;
}

%typemap(out, fragment=%fragment_name(downcast, typemaptarget))
%ptr(typemaptarget) {
  $result = downcast($1, jenv);
  if (!$1 || !$result)
    SWIG_exception(SWIG_TypeError,"Actual object type could not be
%downcasted. Consider adding derived types to %downcast declaration.");
}
%typemap(out, fragment=%fragment_name(downcast, typemaptarget)) %ptr(const
typemaptarget) {
  $result = downcast($1, jenv);
  if (!$1 || !$result)
    SWIG_exception(SWIG_TypeError,"Actual object type could not be
%downcasted. Consider adding derived types to %downcast declaration.");
}
%typemap(out, fragment=%fragment_name(downcast, typemaptarget))
%ptr(typemaptarget) const& {
  $result = downcast(*$1, jenv);
  if (!$1 || !$result)
    SWIG_exception(SWIG_TypeError,"Actual object type could not be
%downcasted. Consider adding derived types to %downcast declaration.");
}
%typemap(out, fragment=%fragment_name(downcast, typemaptarget)) %ptr(const
typemaptarget) const& {
  $result = downcast(*$1, jenv);
  if (!$1 || !$result)
    SWIG_exception(SWIG_TypeError,"Actual object type could not be
%downcasted. Consider adding derived types to %downcast declaration.");
}

%enddef

--000000000000ea598406373ccd52
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>For a given C++ type being wrapped, is it possible to=
 get the (fully=C2=A0qualified) name of the wrapped type in the target lang=
uage?</div><div><br></div><div>I have many factory methods that return std:=
:shared_ptr&lt;const BaseClass&gt;</div><div>I do wrap and export to java s=
everal types derived from BaseClass</div><div>And I need the runtime wrappe=
r JVM managed type to accurately match those derived types</div><div>I wrot=
e the below %downcast macro</div><div>I have a version of this for python w=
hich works quite nicely. It uses $descriptor(DeriverType) to create the pyt=
hon native extension type</div><div><br></div><div>But JNI code does not se=
em to have any descriptor infrastructure in the module.</div><div><br></div=
><div>Is there a way to make this work in Java?</div><div><br></div><div>Th=
ank you for any help=C2=A0you can provide</div><div><br></div><div><br></di=
v><div><br></div><div>// Helper function for %downcast, to be called for ea=
ch target type<br><br>%define %_downcast_const(Type)<br>=C2=A0 =C2=A0 {<br>=
=C2=A0 =C2=A0 =C2=A0 auto const out =3D %dynptrcast(const Type,ptr);<br>=C2=
=A0 =C2=A0 =C2=A0 if (out)<br>=C2=A0 =C2=A0 =C2=A0 {<br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 auto const clazz =3D jenv-&gt;FindClass(=C2=A0 &gt;&gt;&gt;&gt;&=
gt; I_NEED_THE_JAVA_CLASS_NAME_HERE&lt;&lt;&lt;&lt;=C2=A0 );<br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 if (clazz)<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 {<br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 auto const mid =3D jenv-&gt;GetMethodID(clazz, &qu=
ot;&lt;init&gt;&quot;, &quot;(JZ)V&quot;);<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 if (mid)<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return reinter=
pret_cast&lt;jlong&gt;(jenv-&gt;NewObject(clazz, mid, reinterpret_cast&lt;j=
long&gt;(new %ptr(const Type)(out)), false));<br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 }<br>=C2=A0 =C2=A0 =C2=A0 }<br>=C2=A0 =C2=A0 }<br>%enddef<br><br><br><b=
r>// the actual %downcast macro<br><br>%define %downcast(typemaptarget, Typ=
es...)<br><br>%fragment(%fragment_name(downcast, typemaptarget), &quot;head=
er&quot;) {<br>jlong downcast(%ptr(const typemaptarget) const&amp; ptr, JNI=
Env *jenv)<br>{<br>=C2=A0 if (!ptr)<br>=C2=A0 =C2=A0 return 0; // TODO: che=
ck this is correct<br>=C2=A0 else<br>=C2=A0 {<br>=C2=A0 =C2=A0 %formacro(%_=
downcast_const, Types)<br>=C2=A0 }<br>=C2=A0 return 0;<br>}<br>}<br><br>%ty=
pemap(jni) %ptr(typemaptarget) &quot;jobject&quot;<br>%typemap(jtype) %ptr(=
typemaptarget) #typemaptarget<br>%typemap(jstype) %ptr(typemaptarget) #type=
maptarget<br>%typemap(javaout) %ptr(typemaptarget) {<br>=C2=A0 return $jnic=
all;<br>}<br><br>%typemap(out, fragment=3D%fragment_name(downcast, typemapt=
arget)) %ptr(typemaptarget) {<br>=C2=A0 $result =3D downcast($1, jenv);<br>=
=C2=A0 if (!$1 || !$result)<br>=C2=A0 =C2=A0 SWIG_exception(SWIG_TypeError,=
&quot;Actual object type could not be %downcasted. Consider adding derived =
types to %downcast declaration.&quot;);<br>}<br>%typemap(out, fragment=3D%f=
ragment_name(downcast, typemaptarget)) %ptr(const typemaptarget) {<br>=C2=
=A0 $result =3D downcast($1, jenv);<br>=C2=A0 if (!$1 || !$result)<br>=C2=
=A0 =C2=A0 SWIG_exception(SWIG_TypeError,&quot;Actual object type could not=
 be %downcasted. Consider adding derived types to %downcast declaration.&qu=
ot;);<br>}<br>%typemap(out, fragment=3D%fragment_name(downcast, typemaptarg=
et)) %ptr(typemaptarget) const&amp; {<br>=C2=A0 $result =3D downcast(*$1, j=
env);<br>=C2=A0 if (!$1 || !$result)<br>=C2=A0 =C2=A0 SWIG_exception(SWIG_T=
ypeError,&quot;Actual object type could not be %downcasted. Consider adding=
 derived types to %downcast declaration.&quot;);<br>}<br>%typemap(out, frag=
ment=3D%fragment_name(downcast, typemaptarget)) %ptr(const typemaptarget) c=
onst&amp; {<br>=C2=A0 $result =3D downcast(*$1, jenv);<br>=C2=A0 if (!$1 ||=
 !$result)<br>=C2=A0 =C2=A0 SWIG_exception(SWIG_TypeError,&quot;Actual obje=
ct type could not be %downcasted. Consider adding derived types to %downcas=
t declaration.&quot;);<br>}<br><br>%enddef<br></div></div>

--000000000000ea598406373ccd52--


--===============3830934274467218281==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline


--===============3830934274467218281==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Swig-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/swig-user

--===============3830934274467218281==--