why does SWIG make illegal wrapper from in and argout typemaps? - swig

I am trying to write an argout SWIG typemap.
From this interface foobar.i file, which seems perfectly legal to me:
%{
void f(int arg[2]) {}
%}
%typemap(in, numinputs = 0) int [ANY] {}
%typemap(argout) int arg[ANY] {
PySequence_SetItem($input, 0, PyInt_FromLong(0));
}
void f(int arg[2]) {}
SWIG compiles an illegal foobar_wrap.cxx file, because it contains the following fragment:
PySequence_SetItem(, 0, PyInt_FromLong(0));
replacing $input with nothing. If I omit the in typemap, then the wrapper is correct.
Why?
I just want to ignore the input, and fill up the array on the output. The SWIG manual clearly says to use numinputs=0.

OK I figured it out. I guess my beef here is with the manual. The manual does not say, how to output results, not as printout, but as filled in "output" arguments. For example, the manual clearly states that $input is available for argout typemap. Wrong, it is not available, if there is also a matching (in, numinputs) typemap.

Related

Error when calling static method c++

Consider the following code:
Automobile.h
class Automobile
{
static string m_stCityCode;
static bool CheckCityCode(const Automobile& obj);
};
Automobile.cpp
bool Automobile::CheckCityCode(const Automobile& obj)
{
return m_stCityCode == obj.m_stCityCode;
}
int main()
{
//do something
}
I get the following error
"Severity Code Description Project File Line Suppression State
Error LNK2001 unresolved external symbol "public: static class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > Automobile::m_stCityCode"
(?m_stCityCode#Automobile##2V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##A) myPro C:\Users\zhivko.rusev\Documents\Visual
Studio 2015\Projects\myPro\myPro\Calls.obj 1 "
I would appreciate every help for solving this problem. Thanks in advance!
The static member needs to be defined. The error message is the linker's way of telling you it isn't. Your code declares the static member but does not define it.
To define it, in a single compilation unit (i.e. a non-header source file) simply add a line at file scope after including the header file
#include "Automobile.h"
std::string Automobile::m_stCityCode = ""; // change the initialiser to whatever suits
Do this in exactly one compilation unit. One is necessary to define the symbols. Multiple definitions (e.g. in multiple source files within your project) will cause the linker to complain about symbols being defined multiple times.
There are other problems in your code as shown, beyond what you have asked about, but I'll assume that just reflects you having left information out.

how to wrap a C++ argument-less macro with SWIG?

I read here how to wrap this macro FOOBAR in SWIG:
class foobar {
public:
static void method() {}
};
#define FOOBAR() foobar().method()
The solution is to include this in SWIG interface:
void FOOBAR();
However, suppose I drop () so that my macro is
#define FOOBAR foobar().method()
This is still perfectly legitimate macro I can use in C++. How do I wrap this, so I can say on Python command line:
>>>FOOBAR
To clarify, since this seems to be confusing. I purposely chose the method to return nothing. I did that, so that the irrelevant question of "what is it supposed to return" is not considered. However, people still seem to want to consider it.
OK then, in C++, FOOBAR has meaning - it is a certain object, I can call FOOBAR.someMethod(). I want that on Python command line, it also be an object (the equivalent one), which will behave the same, I also want to call FOOBAR.someMethod() and have it behave the same as in C++.
I am sorry, but I assumed, that in the context of SWIG, the above explanation is obvious and unnecessary, and is contained in the abbreviation "wrap".
%pythoncode may be what you want. Example:
%module x
%inline %{
class foobar {
public:
static void method() {}
};
#define FOOBAR foobar().method()
%}
%pythoncode %{
FOOBAR = foobar().method
%}
Result:
>>> from x import *
>>> FOOBAR
<built-in function foobar_method>

How can I use SWIG to handle a JAVA to C++ call with a pointer-to-pointer argout argument?

The problem involved a JAVA call to a C-function (API) which returned a pointer-to-pointer as an argout argument. I was trying to call the C API from JAVA and I had no way to modify the API.
Using SWIG typemap to pass pointer-to-pointer:
Here is another approach using typemaps. It is targetting Perl, not Java, but the concepts are the same. And I finally managed to get it working using typemaps and no helper functions:
For this function:
typedef void * MyType;
int getblock( int a, int b, MyType *block );
I have 2 typemaps:
%typemap(perl5, in, numinputs=0) void ** data( void * scrap )
{
$1 = &scrap;
}
%typemap(perl5, argout) void ** data
{
SV* tempsv = sv_newmortal();
if ( argvi >= items ) EXTEND(sp,1);
SWIG_MakePtr( tempsv, (void *)*$1, $descriptor(void *), 0);
$result = tempsv;
argvi++;
}
And the function is defined as:
int getblock( int a, int b, void ** data );
In my swig .i file. Now, this passes back an opaque pointer in the argout typemap, becaust that's what useful for this particular situation, however, you could replace the SWIG_MakePtr line with stuff to actually do stuff with the data in the pointer if you wanted to. Also, when I want to pass the pointer into a function, I have a typemap that looks like this:
%typemap(perl5, in) void * data
{
if ( !(SvROK($input)) croak( "Not a reference...\n" );
if ( SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0 ) == -1 )
croak( "Couldn't convert $1 to $1_descriptor\n");
}
And the function is defined as:
int useblock( void * data );
In my swig .i file.
Obviously, this is all perl, but should map pretty directly to Java as far as the typemap architecture goes. Hope it helps...
[Swig] Java: Using C helper function to pass pointer-to-pointer
The problem involved a JAVA call to a C-function (API) which returned a pointer-to-pointer as an argout argument. I was trying to call the C API from JAVA and I had no way to modify the API.
The API.h header file contained:
extern int ReadMessage(HEADER **hdr);
The original C-call looked like:
HEADER *hdr;
int status;
status = ReadMessage(&hdr);
The function of the API was to store data at the memory location specified by the pointer-to-pointer.
I tried to use SWIG to create the appropriate interface file. SWIG.i created the file SWIGTYPE_p_p_header.java from API.h. The problem is the SWIGTYPE_p_p_header constructor initialized swigCPtr to 0.
The JAVA call looked like:
SWIGTYPE_p_p_header hdr = new SWIGTYPE_p_p_header();
status = SWIG.ReadMessage(hdr);
But when I called the API from JAVA the ptr was always 0.
I finally gave up passing the pointer-to-pointer as an input argument. Instead I defined another C-function in SWIG.i to return the pointer-to-pointer in a return value. I thought it was a Kludge ... but it worked!
You may want to try this:
SWIG.i looks like:
// return pointer-to-pointer
%inline %{
HEADER *ReadMessageHelper() {
HEADER *hdr;
int returnValue;
returnValue = ReadMessage(&hdr);
if (returnValue!= 1) hdr = NULL;
return hdr;
}%}
The inline function above could leak memory as Java won't take ownership of the memory created by ReadMessageHelper, since the HEADER instance iscreated on the heap.
The fix for the memory leak is to define ReadMessageHelper as a newobject in order for Java to take control of the memory.
%newobject ReadMessageHelper();
JAVA call now would look like:
HEADER hdr;
hdr = SWIG.ReadMessageHelper();
If you are lucky, as I was, you may have another API available to release the message buffer. In which case, you wouldn’t have to do the previous step.
William Fulton, the SWIG guru, had this to say about the approach above:
“I wouldn't see the helper function as a kludge, more the simplest solution to a tricky problem. Consider what the equivalent pure 100% Java code would be for ReadMessage(). I don't think there is an equivalent as Java classes are passed by reference and there is no such thing as a reference to a reference, or pointer to a pointer in Java. In the C function you have, a HEADER instances is created by ReadMessage and passed back to the caller. I don't see how one can do the equivalent in Java without providing some wrapper class around HEADER and passing the wrapper to the ReadMessage function. At the end of the day, ReadMessage returns a newly created HEADER and the Java way of returning newly created objects is to return it in the return value, not via a parameter.”

gcroot has no value

I have a curious problem with a managed object in unmanaged code. I have this C++/CLI module that bridges C++ and C# code. I have a structure like this:
template <class T>
struct ManagedReference
{
gcroot<T^> addonHost;
}
Now, at some point I create an instance of this managed reference and set the addonHost. All is well, I am able to use the handle.
However, in some cases (would require to much contextual description I'm afraid) the value cannot be evaluated:
In this case, calling a method with addonHost results in a "Entry point for found" exception.
As you can see from the screenshots, it is not two difference instances, two different handles. It's the very same. I don't understand how come in some situation the "value" is not evaluated. And maybe how I could catch that. Because it's not null.
What I should also mention is that I have several gcroot<T> and all of them have this problem, except one that is a gcroot<System::String>.
UPDATE
Here is what debugger shows during execution. The object is created and available, then at some point, the value is 'vanishing', and at the next call it's still there. But this is very reproducible. It's not random.
handle 0x0E1618EC void*
value 0x106396d8 { m_host=0x10638e04 } <-- object is available here
handle 0x0E1618EC void*
value 0x1020e558 { m_host=0x1020e4f0 } <-- object moved in memory
handle 0x0E1618EC void*
value <-- no value here
handle 0x0E1618EC void*
value 0x1020e558 { m_host=0x1020e4f0 } <-- object 'is back'
Maybe it would help to initialize the gcroot. Try:
template <class T>
struct ManagedReference
{
gcroot<T^> addonHost;
ManagedReference() : addonHost(nullptr) {}
};

why does the following program give error when it is checked with cppcheck analyzer

#include "stdio.h"
int main (void) {
char xx[1000] = "hello";
sprintf (xx, "xyzzy plugh %s", xx);
printf ("%s\n", xx);
return 0;
}
::::(error) Undefined behaviour: xx is used wrong in call to sprintf or snprintf. Quote: If copying takes place between objects that overlap as a result of a call to sprintf() or snprintf(), the results are undefined.
Precisely what it says. You are passing the same array both as input and output to sprintf(), which is not a supported usage as there is no guarantee that sprintf will write the output string in ascending order.
You are writing into char array xx as well as using it as the source for the copy. This behaviour is undefined. Here's an existing question about the situation:
Is sprintf(buffer, "%s […]", buffer, […]) safe?