I am using swig 4.0.2 to generate a package for tcl use.
The source .i file contains lots of classes and the generated _wrap.cpp file contains the all the classes with their methods as I would expect and everything compiles ok with no warnings.
However, for at least 1 class, when I come to call a method on a instance from a tcl script I get a runtime error saying the method does not exist. The error also dumps out all the available methods of the class. The method I am trying to call, along with a few others, does not exist in that list.
Invalid method. Must be one of: configure cget -acquire -disown -delete ...
There doesn't appear to be any pattern to which methods are not in the list though it is consistent which methods are missing.
The missing methods are scattered through the declared swig interface. ie they aren't at the beginning or end, nor all in one block. There is no pattern to their names nor function signature that I can see.
The function being run when the error occurs is SWIG_Tcl_MethodCommand: a function generated by swig. It is responsible for looking up the method by name and printing out the error code.
The function wrappers all exist and are referenced in the class's swig_method array.
I would have imagined that if a method was not going to be found by the look up it would be all or nothing.
Does anyone have ideas where I could look for errors?
I'm afraid I haven't been able to isolate into a small testcase that I can share.
I'm using swig 4.02, generating code for tcl8 and compiling under c++ 14.
The problem is caused by copy and paste code.
A second swig package exists in the Project I'm working on. It redeclares the same class interface but with some methods missing!
If I sync up the declarations then everything works.
This leaves the question of how the original code with unsynced swig interfaces (that was generated with swig1.0) ever worked.
Related
I'm writing function libraries in Python 2.7.8, to use in some UAT testing using froglogic Squish. It's for my employer, so I'm not sure how much I can share and still conform to company privacy regulations.
Early in the development, I put some functions in some very small files. There was one file that contained only a single function. I could import the file and use the function with no problem.
I am at a point where I want to consolidate some of those tiny files into a larger file. For some reason that completely eludes me, some of the functions that I copy/pasted into this larger file, are not being found, and a "NameError: global name 'My_variableStringVerify' is not defined" error is displayed, for example. (I just added the "My_", in case there was a name collision with some other function...)
This worked with the EXACT same simple function in a separate 'module'. Other functions in this python file -- appearing both before and after this function in the new, expanded module -- are being found and used without problems. The only module this function needs is re. I am importing that. I deleted all the pyc files in the directory, in case that was not getting updated (I'm pretty sure it was, from the datetime on the pyc file).
I have created and used dozens of functions in a dozen of my 'library modules', all with no issues. What's so special about this trivial, piece of crap function, as a part of a different module? It worked before, and it STILL works -- as long as I do not try to use it from the new library module.
I'm not python guru, but I have been doing this kind of thing for years...
Ugh. What a fool. The answer was in the error, after all: "global name xxx is not found". I was trying to use the function directly inside a Squish API call, which is the global scope. Moving the call to my function outside of the Squish API call (using it in the local scope), it worked fine.
The detail that surprised me: I was using "from foo import *", in both cases (before and after adding it to another 'library' module of mine).
When this one function was THE ONLY function in foo, I was able to use it in the global scope successfully.
When it was just one of many functions in foo-extended (names have been changed, to protect the innocent), I could NOT use it in the global scope. I had to reference it in the local scope.
After spending more time reading https://docs.python.org/2.0/ref/import.html (yes, it's old), I'm surprised it appeared in the global scope in either case. That page did state that "(The current implementation does not enforce the latter two restrictions, but programs should not abuse this freedom, as future implementations may enforce them or silently change the meaning of the program.)" about scope restrictions with the "from foo import *" statement.
I guess I found an edge case that somehow skirted the restriction in this implementation.
Still... what a maroon! Verifies my statement that I am no python guru.
Based on the Kaleidoscope and Kaleidoscope with MCJIT tutorials, I have code to create a Module and function and call it using MCJIT. The function needs a prototype:
auto ft = llvm::FunctionType::get(llvm::Type::getInt32Ty(Context), argTypes, false);
However, the example only covers Double as parameters and return values (the above uses an int). To do anything advanced, you need to pass things like classes and containers.
How do you use existing C++ classes in the module?
Sure, you can link to any library you want, but you need to declare function prototypes to use them. If the library API has classes, how do you declare them?
What I want is something like this:
auto ft = llvm::FunctionType::get(llvm::Type::getStructTy("class.std::string"), argTypes, false);
where class.std::string has been imported from string.h.
The LLVM API only has primitive types. You can define structs to represent the classes, but this is way too hard to do manually (and not portable).
A way to do it might be to compile the class to bitcode and read it into a module, but I want to avoid temporary files if possible. Also I'm not sure how to extract the type from the module but it should be possible. I tried this on a header file of one of my classes (I renamed the header file to a cpp file otherwise clang would make into a .gch precompiled header) and the result was just a constant... maybe it was optimised out? I tried it on the cpp file and it resulted in 36000 lines of code...
Then I found this page. Instead of using the LLVM API, I should use the Clang API because Clang, as a compiler, can compile the code into a Module. Then I can use the LLVM API with the imported Modules. Is this the right way to go? Any working source code is appreciated because it took forever just to get function calling working (the tutorials are out of date and documentation is scarce).
The way I would do it is to compile the class to LLVM IR, and then link the two modules. Then, there's two options to extract the type from the module:
First, you can use the llvm::TypeFinder. The way you use it is by creating it, and then calling run() on it with the module as an argument. This code snippet will print out all of the types in the module:
llvm::TypeFinder type_finder;
type_finder.run(module, true);
for (auto t : type_finder) {
std::cout << t->getName().str() << std::endl;
}
Alternatively, it's possible to use Module's getIdentifiedStructTypes() method and iterate over the resulting vector in the same way as above.
So far, I was able to call member functions which belong to a class for a struct. CEDET can give the suggestion nicely. However, for non-member functions, such as functions in C, which usually does not belong to anything i.e. functions like sort, qsort.... I can only auto-complete with CEDET if I have an instance of a class/struct. Without it, I have to type the function manually.
Is there a way to have code suggestion for such functions?
CEDET works fine for such functions - you need to be sure, that all necessary headers are included into your source code. You can also force CEDET to re-parse buffer with M-x bovinate command. But it's better to use CEDET from bzr repository, because fixes for C & C++ mode are made very often.
If it still don't working look to output of M-x semantic-analyze-debug-assist command, and post results to cedet-devel list
I'm writing a wrapper class around the V8 engine so that eventually I'll be able to do something like this
script->createClass("Test");
script->getClass("Test")->addFunction("funct1",testfunct1);
script->getClass("Test")->addVariable("x",setter,getter);
So far I can create classes and add functions to them and it works perfectly, however I have encountered a problem with adding variables.
My class template is stored as such
Persistent<Object> classInstance;
and I try to add an Accessor like this:
this->classInstance->SetAccessor(String::New(variableName),setter,getter);
Compiling this code gives me the error that v8::Object doesn't have a SetAccessor function (though I've seen doxygen documentation that says otherwise).
So my question is: How can I fix this? Is it possible to cast an Object to an ObjectTemplate?
SetAccessor on Object is available as of V8 2.2.12, which was released May 2010. (Before that, it was indeed only available on ObjectTemplate.) You should probably update your copy of V8.
Whilst refactoring some old code I realised that a particular header file was full of function declarations for functions long since removed from the .cpp file. Does anyone know of a tool that could find (and strip) these automatically?
You could if possible make a test.cpp file to call them all, the linker will flag the ones that have no code as unresolved, this way your test code only need compile and not worry about actually running.
PC-lint can be tunned for dedicated purpose:
I tested the following code against for your question:
void foo(int );
int main()
{
return 0;
}
lint.bat test_unused.cpp
and got the following result:
============================================================
--- Module: test_unused.cpp (C++)
--- Wrap-up for Module: test_unused.cpp
Info 752: local declarator 'foo(int)' (line 2, file test_unused.cpp) not referenced
test_unused.cpp(2) : Info 830: Location cited in prior message
============================================================
So you can pass the warning number 752 for your puropse:
lint.bat -"e*" +e752 test_unused.cpp
-e"*" will remove all the warnings and +e752 will turn on this specific one
If you index to code with Doxygen you can see from where is each function referenced. However, you would have to browse through each class (1 HTML page per class) and scan for those that don't have anything pointing to them.
Alternatively, you could use ctags to generate list of all functions in the code, and then use objdump or some similar tool to get list of all function in .o files - and then compare those lists. However, this can be problematic due to name mangling.
I don't think there is such thing because some functions not having a body in the actual source tree might be defined in some external library. This can only be done by creating a script which makes a list of declared functions in a header and verifies if they are sometimes called.
I have a C++ ftplugin for vim that is able is check and report unmatched functions -- vimmers, the ftplugin suite is not yet straightforward to install. The ftplugin is based on ctags results (hence its heuristic could be easily adapted to other environments), sometimes there are false positives in the case of inline functions.
HTH,
In addition Doxygen (#Milan Babuskov), you can see if there are warnings for this in your compiler. E.g. gcc has -Wunused-function for static functions; -fdump-ipa-cgraph.
I've heard good things about PC-Lint, but I imagine it's probably overkill for your needs.