I maintain software that is implemented in C++ but must have interfaces in multiple languages including Java and .NET, but also including delphi and VB6. Plus, it has to work on multiple platforms (so Java needs to work on unix).
The way it was done was to use a single DLL exporting plain C functions using primitive types. For example, given an class Foo:
long MY_EXPORT_FLAG FooCreate()
{
return (long)new Foo();
}
void MY_EXPORT_FLAG FooDestroy(long Handle)
{
delete (Foo*)Handle;
}
void MY_EXPORT_FLAG BarMethod(long Handle, const char* pStr1, long* pReturnValue)
{
*pReturnValue = ((Foo*)Handle)->BarMethod( pStr1 );
}
Then your JNI/.NET/VB6/Delphi code implements language specific class wrappers, but call these C dll functions. Each class wrapper would contain a Handle, and pass it into the C functions.
This works quite well because most languages tend to use C as the lowest common denominator, so as long as you can export your interfaces through a thin C api you can build interfaces for other languages.
We export a C (and not C++) api in the DLL because function signatures are much more standardized across platforms.
Don't forget, that on C# and Java, you'll have to deal with multibyte string encoding, so you should figure out how to transcode your strings to/from your C++ code. This typically involves knowing about locales, or you can cheap out and just support UTF-8.