mirror of
https://github.com/cemu-project/idapython.git
synced 2024-11-24 01:59:18 +01:00
- Experimental: integrated Hex-Rays Decompiler bindings that were contributed by EiNSTeiN:
https://github.com/EiNSTeiN-/hexrays-python - Added '--with-hexrays' switch to the build script so it wrap Hex-Rays Decompiler API - Added one Hex-Rays decompiler sample: vds1.py
This commit is contained in:
parent
ce06fdd7d2
commit
db58b31711
@ -42,6 +42,9 @@ Make sure all the needed tools (compiler, swig) are on the PATH.
|
|||||||
swigsdk-versions/x.y/ - A supported version of the IDA SDK
|
swigsdk-versions/x.y/ - A supported version of the IDA SDK
|
||||||
idapython/ - IDAPython source code
|
idapython/ - IDAPython source code
|
||||||
|
|
||||||
|
Note: To build with Hex-Rays decompiler support, please copy hexrays.hpp from
|
||||||
|
the decompiler SDK folder into IDA's include folder (in the SDK).
|
||||||
|
|
||||||
2. On Mac OS X copy libida.dylib from the IDA install directory to
|
2. On Mac OS X copy libida.dylib from the IDA install directory to
|
||||||
swigsdk-versions/x.y/lib/x86_mac_gcc_32/
|
swigsdk-versions/x.y/lib/x86_mac_gcc_32/
|
||||||
and libida64.dylib to
|
and libida64.dylib to
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
|
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
|
||||||
|
|
||||||
|
Changes from version 1.5.6 to 1.5.7
|
||||||
|
------------------------------------
|
||||||
|
- Added '--with-hexrays' switch to the build script so it wrap Hex-Rays Decompiler API
|
||||||
|
- Experimental: integrated Hex-Rays Decompiler bindings that were contributed by EiNSTeiN:
|
||||||
|
https://github.com/EiNSTeiN-/hexrays-python
|
||||||
|
- Added one Hex-Rays decompiler sample: vds1.py
|
||||||
|
- Fixed small mismatch between SWIG define and CL defines (/DNO_OBSOLETE_FUNCS)
|
||||||
|
- Use print_type2() instead of the deprecated function print_type()
|
||||||
|
|
||||||
Changes from version 1.5.5 to 1.5.6
|
Changes from version 1.5.5 to 1.5.6
|
||||||
------------------------------------
|
------------------------------------
|
||||||
- IDA Pro 6.4 support
|
- IDA Pro 6.4 support
|
||||||
|
77
build.py
77
build.py
@ -45,6 +45,10 @@ PYTHON_MINOR_VERSION = int(platform.python_version()[2])
|
|||||||
# Find Python headers
|
# Find Python headers
|
||||||
PYTHON_INCLUDE_DIRECTORY = sysconfig.get_config_var('INCLUDEPY')
|
PYTHON_INCLUDE_DIRECTORY = sysconfig.get_config_var('INCLUDEPY')
|
||||||
|
|
||||||
|
S_EA64 = 'ea64'
|
||||||
|
S_WITH_HEXRAYS = 'with-hexrays'
|
||||||
|
S_NO_OPT = 'no-opt'
|
||||||
|
|
||||||
# Swig command-line parameters
|
# Swig command-line parameters
|
||||||
SWIG_OPTIONS = '-modern -python -c++ -w451 -shadow -D__GNUC__ -DNO_OBSOLETE_FUNCS'
|
SWIG_OPTIONS = '-modern -python -c++ -w451 -shadow -D__GNUC__ -DNO_OBSOLETE_FUNCS'
|
||||||
|
|
||||||
@ -61,6 +65,7 @@ COMMON_MACROS = [
|
|||||||
# Common includes for all compilations
|
# Common includes for all compilations
|
||||||
COMMON_INCLUDES = [ ".", "swig" ]
|
COMMON_INCLUDES = [ ".", "swig" ]
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
# List files for the binary distribution
|
# List files for the binary distribution
|
||||||
BINDIST_MANIFEST = [
|
BINDIST_MANIFEST = [
|
||||||
"README.txt",
|
"README.txt",
|
||||||
@ -104,6 +109,7 @@ BINDIST_MANIFEST = [
|
|||||||
"examples/ex_imports.py"
|
"examples/ex_imports.py"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
# List files for the source distribution (appended to binary list)
|
# List files for the source distribution (appended to binary list)
|
||||||
SRCDIST_MANIFEST = [
|
SRCDIST_MANIFEST = [
|
||||||
"BUILDING.txt",
|
"BUILDING.txt",
|
||||||
@ -150,14 +156,31 @@ SRCDIST_MANIFEST = [
|
|||||||
"swig/xref.i",
|
"swig/xref.i",
|
||||||
"swig/graph.i",
|
"swig/graph.i",
|
||||||
"swig/fpro.i",
|
"swig/fpro.i",
|
||||||
|
"swig/hexrays.i",
|
||||||
"tools/gendocs.py",
|
"tools/gendocs.py",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
def parse_options(args):
|
||||||
|
"""Parse arguments and returned a dictionary of options"""
|
||||||
|
|
||||||
|
no_opt = '--' + S_NO_OPT in sys.argv
|
||||||
|
ea64 = '--' + S_EA64 in sys.argv
|
||||||
|
with_hexrays = '--' + S_WITH_HEXRAYS in sys.argv
|
||||||
|
|
||||||
|
return {
|
||||||
|
S_EA64: ea64,
|
||||||
|
S_WITH_HEXRAYS: with_hexrays,
|
||||||
|
S_NO_OPT: no_opt
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
class BuilderBase:
|
class BuilderBase:
|
||||||
""" Base class for builders """
|
""" Base class for builders """
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def compile(self, source, objectname=None, includes=[], macros=[]):
|
def compile(self, source, objectname=None, includes=[], macros=[]):
|
||||||
"""
|
"""
|
||||||
Compile the source file
|
Compile the source file
|
||||||
@ -187,6 +210,7 @@ class BuilderBase:
|
|||||||
print cmdstring
|
print cmdstring
|
||||||
return os.system(cmdstring)
|
return os.system(cmdstring)
|
||||||
|
|
||||||
|
|
||||||
def link(self, objects, outfile, libpaths=[], libraries=[], extra_parameters=None):
|
def link(self, objects, outfile, libpaths=[], libraries=[], extra_parameters=None):
|
||||||
""" Link the binary from objects and libraries """
|
""" Link the binary from objects and libraries """
|
||||||
cmdstring = "%s %s %s" % (self.linker,
|
cmdstring = "%s %s %s" % (self.linker,
|
||||||
@ -217,6 +241,7 @@ class BuilderBase:
|
|||||||
return macrostring
|
return macrostring
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
class GCCBuilder(BuilderBase):
|
class GCCBuilder(BuilderBase):
|
||||||
""" Generic GCC compiler class """
|
""" Generic GCC compiler class """
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -241,6 +266,7 @@ class GCCBuilder(BuilderBase):
|
|||||||
return "-o %s" % filename
|
return "-o %s" % filename
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
class MSVCBuilder(BuilderBase):
|
class MSVCBuilder(BuilderBase):
|
||||||
""" Generic Visual C compiler class """
|
""" Generic Visual C compiler class """
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -266,7 +292,7 @@ class MSVCBuilder(BuilderBase):
|
|||||||
def linker_out_string(self, filename):
|
def linker_out_string(self, filename):
|
||||||
return "/out:%s" % filename
|
return "/out:%s" % filename
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
def build_distribution(manifest, distrootdir, ea64, nukeold):
|
def build_distribution(manifest, distrootdir, ea64, nukeold):
|
||||||
""" Create a distibution to a directory and a ZIP file """
|
""" Create a distibution to a directory and a ZIP file """
|
||||||
# (Re)create the output directory
|
# (Re)create the output directory
|
||||||
@ -307,7 +333,17 @@ def build_distribution(manifest, distrootdir, ea64, nukeold):
|
|||||||
zip.close()
|
zip.close()
|
||||||
|
|
||||||
|
|
||||||
def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
# -----------------------------------------------------------------------
|
||||||
|
def build_plugin(
|
||||||
|
platform,
|
||||||
|
idasdkdir,
|
||||||
|
plugin_name,
|
||||||
|
options):
|
||||||
|
|
||||||
|
# Get the arguments
|
||||||
|
ea64 = options[S_EA64]
|
||||||
|
with_hexrays = options[S_WITH_HEXRAYS]
|
||||||
|
|
||||||
global SWIG_OPTIONS
|
global SWIG_OPTIONS
|
||||||
""" Build the plugin from the SWIG wrapper and plugin main source """
|
""" Build the plugin from the SWIG wrapper and plugin main source """
|
||||||
# Path to the IDA SDK headers
|
# Path to the IDA SDK headers
|
||||||
@ -334,6 +370,7 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
|||||||
ida_lib = "ida.lib"
|
ida_lib = "ida.lib"
|
||||||
SWIG_OPTIONS += " -D__NT__ "
|
SWIG_OPTIONS += " -D__NT__ "
|
||||||
extra_link_parameters = ""
|
extra_link_parameters = ""
|
||||||
|
if not options[S_NO_OPT]:
|
||||||
builder.compiler_parameters += " -Ox"
|
builder.compiler_parameters += " -Ox"
|
||||||
# Platform-specific settings for the Mac OS X build
|
# Platform-specific settings for the Mac OS X build
|
||||||
elif platform == "macosx":
|
elif platform == "macosx":
|
||||||
@ -353,6 +390,11 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
|||||||
if ea64:
|
if ea64:
|
||||||
platform_macros.append("__EA64__")
|
platform_macros.append("__EA64__")
|
||||||
|
|
||||||
|
# Build with Hex-Rays decompiler
|
||||||
|
if with_hexrays:
|
||||||
|
platform_macros.append("WITH_HEXRAYS")
|
||||||
|
SWIG_OPTIONS += ' -DWITH_HEXRAYS '
|
||||||
|
|
||||||
platform_macros.append("NDEBUG")
|
platform_macros.append("NDEBUG")
|
||||||
|
|
||||||
if not '--no-early-load' in sys.argv:
|
if not '--no-early-load' in sys.argv:
|
||||||
@ -388,6 +430,7 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
|||||||
extra_link_parameters)
|
extra_link_parameters)
|
||||||
assert res == 0, "Failed to link the plugin binary"
|
assert res == 0, "Failed to link the plugin binary"
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
def detect_platform(ea64):
|
def detect_platform(ea64):
|
||||||
# Detect the platform
|
# Detect the platform
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
@ -410,7 +453,9 @@ def detect_platform(ea64):
|
|||||||
|
|
||||||
return (system, platform_string, plugin_name)
|
return (system, platform_string, plugin_name)
|
||||||
|
|
||||||
def build_binary_package(ea64, nukeold):
|
# -----------------------------------------------------------------------
|
||||||
|
def build_binary_package(options, nukeold):
|
||||||
|
ea64 = options[S_EA64]
|
||||||
system, platform_string, plugin_name = detect_platform(ea64)
|
system, platform_string, plugin_name = detect_platform(ea64)
|
||||||
BINDISTDIR = "idapython-%d.%d.%d_ida%d.%d_py%d.%d_%s" % (VERSION_MAJOR,
|
BINDISTDIR = "idapython-%d.%d.%d_ida%d.%d_py%d.%d_%s" % (VERSION_MAJOR,
|
||||||
VERSION_MINOR,
|
VERSION_MINOR,
|
||||||
@ -421,7 +466,7 @@ def build_binary_package(ea64, nukeold):
|
|||||||
PYTHON_MINOR_VERSION,
|
PYTHON_MINOR_VERSION,
|
||||||
platform_string)
|
platform_string)
|
||||||
# Build the plugin
|
# Build the plugin
|
||||||
build_plugin(platform_string, IDA_SDK, plugin_name, ea64)
|
build_plugin(platform_string, IDA_SDK, plugin_name, options)
|
||||||
|
|
||||||
# Build the binary distribution
|
# Build the binary distribution
|
||||||
binmanifest = []
|
binmanifest = []
|
||||||
@ -436,6 +481,7 @@ def build_binary_package(ea64, nukeold):
|
|||||||
build_distribution(binmanifest, BINDISTDIR, ea64, nukeold)
|
build_distribution(binmanifest, BINDISTDIR, ea64, nukeold)
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
def build_source_package():
|
def build_source_package():
|
||||||
""" Build a directory and a ZIP file with all the sources """
|
""" Build a directory and a ZIP file with all the sources """
|
||||||
SRCDISTDIR = "idapython-%d.%d.%d" % (VERSION_MAJOR,
|
SRCDISTDIR = "idapython-%d.%d.%d" % (VERSION_MAJOR,
|
||||||
@ -448,6 +494,7 @@ def build_source_package():
|
|||||||
srcmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py"])
|
srcmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py"])
|
||||||
build_distribution(srcmanifest, SRCDISTDIR, ea64=False, nukeold=True)
|
build_distribution(srcmanifest, SRCDISTDIR, ea64=False, nukeold=True)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
def gen_docs(z = False):
|
def gen_docs(z = False):
|
||||||
print "Generating documentation....."
|
print "Generating documentation....."
|
||||||
old_dir = os.getcwd()
|
old_dir = os.getcwd()
|
||||||
@ -494,6 +541,7 @@ def gen_docs(z = False):
|
|||||||
os.chdir(old_dir)
|
os.chdir(old_dir)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
def usage():
|
def usage():
|
||||||
print """IDAPython build script.
|
print """IDAPython build script.
|
||||||
|
|
||||||
@ -504,23 +552,36 @@ Available switches:
|
|||||||
Used with '--doc' switch. It will compress the generated documentation
|
Used with '--doc' switch. It will compress the generated documentation
|
||||||
--ea64:
|
--ea64:
|
||||||
Builds also the 64bit version of the plugin
|
Builds also the 64bit version of the plugin
|
||||||
|
--with-hexrays:
|
||||||
|
Build with the Hex-Rays Decompiler wrappings
|
||||||
--no-early-load:
|
--no-early-load:
|
||||||
The plugin will be compiled as normal plugin
|
The plugin will be compiled as normal plugin
|
||||||
This switch disables processor, plugin and loader scripts
|
This switch disables processor, plugin and loader scripts
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
def main():
|
def main():
|
||||||
if '--help' in sys.argv:
|
if '--help' in sys.argv:
|
||||||
return usage()
|
return usage()
|
||||||
elif '--doc' in sys.argv:
|
elif '--doc' in sys.argv:
|
||||||
return gen_docs(z = '--zip' in sys.argv)
|
return gen_docs(z = '--zip' in sys.argv)
|
||||||
|
|
||||||
# Do 64-bit build?
|
# Parse options
|
||||||
ea64 = '--ea64' in sys.argv
|
options = parse_options(sys.argv)
|
||||||
build_binary_package(ea64=False, nukeold=True)
|
ea64 = options[S_EA64]
|
||||||
|
|
||||||
|
# Always build the non __EA64__ version
|
||||||
|
options[S_EA64] = False
|
||||||
|
build_binary_package(options, nukeold=True)
|
||||||
|
|
||||||
|
# Rebuild package with __EA64__ if needed
|
||||||
if ea64:
|
if ea64:
|
||||||
build_binary_package(ea64=True, nukeold=False)
|
options[S_EA64] = True
|
||||||
|
build_binary_package(options, nukeold=False)
|
||||||
|
|
||||||
|
# Always build the source package
|
||||||
build_source_package()
|
build_source_package()
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
27
examples/vds1.py
Normal file
27
examples/vds1.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import idaapi
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if not idaapi.init_hexrays_plugin():
|
||||||
|
return False
|
||||||
|
|
||||||
|
print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version()
|
||||||
|
|
||||||
|
f = idaapi.get_func(idaapi.get_screen_ea());
|
||||||
|
if f is None:
|
||||||
|
print "Please position the cursor within a function"
|
||||||
|
return True
|
||||||
|
|
||||||
|
cfunc = idaapi.decompile(f);
|
||||||
|
if cfunc is None:
|
||||||
|
print "Failed to decompile!"
|
||||||
|
return True
|
||||||
|
|
||||||
|
sv = cfunc.get_pseudocode();
|
||||||
|
for i in xrange(0, sv.size()):
|
||||||
|
line = idaapi.tag_remove(str(sv[i]));
|
||||||
|
print line
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
if main():
|
||||||
|
idaapi.term_hexrays_plugin();
|
@ -97,7 +97,7 @@
|
|||||||
<ClCompile>
|
<ClCompile>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<AdditionalIncludeDirectories>.\pywraps;..\..\include;\python27\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>.\pywraps;..\..\include;\python27\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>NO_OBSOLETE_FUNCS;_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;USE_STANDARD_FILE_FUNCTIONS;VER_MAJOR=1;VER_MINOR=5;VER_PATCH=3;PLUGINFIX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WITH_HEXRAYS;NO_OBSOLETE_FUNCS;_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;USE_STANDARD_FILE_FUNCTIONS;VER_MAJOR=1;VER_MINOR=5;VER_PATCH=3;PLUGINFIX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<MinimalRebuild>true</MinimalRebuild>
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
@ -302,6 +302,7 @@
|
|||||||
</Bscmake>
|
</Bscmake>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Include="build.py" />
|
||||||
<None Include="BUILDING.txt" />
|
<None Include="BUILDING.txt" />
|
||||||
<None Include="CHANGES.txt" />
|
<None Include="CHANGES.txt" />
|
||||||
<None Include="obj\x86_win_vc_32\idaapi.py" />
|
<None Include="obj\x86_win_vc_32\idaapi.py" />
|
||||||
@ -346,6 +347,7 @@
|
|||||||
<None Include="swig\funcs.i" />
|
<None Include="swig\funcs.i" />
|
||||||
<None Include="swig\gdl.i" />
|
<None Include="swig\gdl.i" />
|
||||||
<None Include="swig\graph.i" />
|
<None Include="swig\graph.i" />
|
||||||
|
<None Include="swig\hexrays.i" />
|
||||||
<None Include="swig\ida.i" />
|
<None Include="swig\ida.i" />
|
||||||
<None Include="swig\idaapi.i" />
|
<None Include="swig\idaapi.i" />
|
||||||
<None Include="swig\idd.i" />
|
<None Include="swig\idd.i" />
|
||||||
|
@ -293,6 +293,12 @@
|
|||||||
<None Include="README.txt">
|
<None Include="README.txt">
|
||||||
<Filter>TEXT</Filter>
|
<Filter>TEXT</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="swig\hexrays.i">
|
||||||
|
<Filter>swig_i</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="build.py">
|
||||||
|
<Filter>py</Filter>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="swig_i">
|
<Filter Include="swig_i">
|
||||||
|
27
python.cpp
27
python.cpp
@ -30,6 +30,12 @@
|
|||||||
#include <diskio.hpp>
|
#include <diskio.hpp>
|
||||||
#include <loader.hpp>
|
#include <loader.hpp>
|
||||||
#include <kernwin.hpp>
|
#include <kernwin.hpp>
|
||||||
|
|
||||||
|
#ifdef WITH_HEXRAYS
|
||||||
|
#include <hexrays.hpp>
|
||||||
|
hexdsp_t *hexdsp = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "pywraps.hpp"
|
#include "pywraps.hpp"
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
@ -1317,13 +1323,15 @@ static bool initsite(void)
|
|||||||
{
|
{
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
Py_Finalize();
|
Py_Finalize();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
Py_DECREF(m);
|
Py_DECREF(m);
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// Initialize the Python environment
|
// Initialize the Python environment
|
||||||
@ -1418,8 +1426,14 @@ bool IDAPython_Init(void)
|
|||||||
// Init the SWIG wrapper
|
// Init the SWIG wrapper
|
||||||
init_idaapi();
|
init_idaapi();
|
||||||
|
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
msg("HexraysPython: Python compiled with DEBUG enabled.\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Set IDAPYTHON_VERSION in Python
|
// Set IDAPYTHON_VERSION in Python
|
||||||
qsnprintf(tmp, sizeof(tmp),
|
qsnprintf(
|
||||||
|
tmp,
|
||||||
|
sizeof(tmp),
|
||||||
"IDAPYTHON_VERSION=(%d, %d, %d, '%s', %d)\n"
|
"IDAPYTHON_VERSION=(%d, %d, %d, '%s', %d)\n"
|
||||||
"IDAPYTHON_REMOVE_CWD_SYS_PATH = %s\n",
|
"IDAPYTHON_REMOVE_CWD_SYS_PATH = %s\n",
|
||||||
VER_MAJOR,
|
VER_MAJOR,
|
||||||
@ -1428,6 +1442,7 @@ bool IDAPython_Init(void)
|
|||||||
VER_STATUS,
|
VER_STATUS,
|
||||||
VER_SERIAL,
|
VER_SERIAL,
|
||||||
g_remove_cwd_sys_path ? "True" : "False");
|
g_remove_cwd_sys_path ? "True" : "False");
|
||||||
|
|
||||||
PyRun_SimpleString(tmp);
|
PyRun_SimpleString(tmp);
|
||||||
|
|
||||||
// Install extlang. Needs to be done before running init.py
|
// Install extlang. Needs to be done before running init.py
|
||||||
@ -1467,7 +1482,11 @@ bool IDAPython_Init(void)
|
|||||||
parse_plugin_options();
|
parse_plugin_options();
|
||||||
|
|
||||||
// Register a RunPythonStatement() function for IDC
|
// Register a RunPythonStatement() function for IDC
|
||||||
set_idc_func_ex(S_IDC_RUNPYTHON_STATEMENT, idc_runpythonstatement, idc_runpythonstatement_args, 0);
|
set_idc_func_ex(
|
||||||
|
S_IDC_RUNPYTHON_STATEMENT,
|
||||||
|
idc_runpythonstatement,
|
||||||
|
idc_runpythonstatement_args,
|
||||||
|
0);
|
||||||
|
|
||||||
// A script specified on the command line is run
|
// A script specified on the command line is run
|
||||||
if ( g_run_when == run_on_init )
|
if ( g_run_when == run_on_init )
|
||||||
|
@ -709,6 +709,7 @@ def RunPythonStatement(stmt):
|
|||||||
#</pydoc>
|
#</pydoc>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// qstrvec_t wrapper
|
// qstrvec_t wrapper
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@ -812,7 +813,7 @@ static bool qstrvec_t_remove(PyObject *self, size_t idx)
|
|||||||
sv->erase(sv->begin()+idx);
|
sv->erase(sv->begin()+idx);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//</inline(py_idaapi)>
|
//</inline(py_idaapi)>
|
||||||
|
|
||||||
|
@ -207,72 +207,72 @@ class PyIdc_cvt_int64__(pyidc_cvt_helper__):
|
|||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
# qstrvec_t clinked object
|
# qstrvec_t clinked object
|
||||||
class qstrvec_t(py_clinked_object_t):
|
# class qstrvec_t(py_clinked_object_t):
|
||||||
"""Class representing an qstrvec_t"""
|
# """Class representing an qstrvec_t"""
|
||||||
|
|
||||||
def __init__(self, items=None):
|
# def __init__(self, items=None):
|
||||||
py_clinked_object_t.__init__(self)
|
# py_clinked_object_t.__init__(self)
|
||||||
# Populate the list if needed
|
# # Populate the list if needed
|
||||||
if items:
|
# if items:
|
||||||
self.from_list(items)
|
# self.from_list(items)
|
||||||
|
|
||||||
def _create_clink(self):
|
# def _create_clink(self):
|
||||||
return _idaapi.qstrvec_t_create()
|
# return _idaapi.qstrvec_t_create()
|
||||||
|
|
||||||
def _del_clink(self, lnk):
|
# def _del_clink(self, lnk):
|
||||||
return _idaapi.qstrvec_t_destroy(lnk)
|
# return _idaapi.qstrvec_t_destroy(lnk)
|
||||||
|
|
||||||
def _get_clink_ptr(self):
|
# def _get_clink_ptr(self):
|
||||||
return _idaapi.qstrvec_t_get_clink_ptr(self)
|
# return _idaapi.qstrvec_t_get_clink_ptr(self)
|
||||||
|
|
||||||
def assign(self, other):
|
# def assign(self, other):
|
||||||
"""Copies the contents of 'other' to 'self'"""
|
# """Copies the contents of 'other' to 'self'"""
|
||||||
return _idaapi.qstrvec_t_assign(self, other)
|
# return _idaapi.qstrvec_t_assign(self, other)
|
||||||
|
|
||||||
def __setitem__(self, idx, s):
|
# def __setitem__(self, idx, s):
|
||||||
"""Sets string at the given index"""
|
# """Sets string at the given index"""
|
||||||
return _idaapi.qstrvec_t_set(self, idx, s)
|
# return _idaapi.qstrvec_t_set(self, idx, s)
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
# def __getitem__(self, idx):
|
||||||
"""Gets the string at the given index"""
|
# """Gets the string at the given index"""
|
||||||
return _idaapi.qstrvec_t_get(self, idx)
|
# return _idaapi.qstrvec_t_get(self, idx)
|
||||||
|
|
||||||
def __get_size(self):
|
# def __get_size(self):
|
||||||
return _idaapi.qstrvec_t_size(self)
|
# return _idaapi.qstrvec_t_size(self)
|
||||||
|
|
||||||
size = property(__get_size)
|
# size = property(__get_size)
|
||||||
"""Returns the count of elements"""
|
# """Returns the count of elements"""
|
||||||
|
|
||||||
def addressof(self, idx):
|
# def addressof(self, idx):
|
||||||
"""Returns the address (as number) of the qstring at the given index"""
|
# """Returns the address (as number) of the qstring at the given index"""
|
||||||
return _idaapi.qstrvec_t_addressof(self, idx)
|
# return _idaapi.qstrvec_t_addressof(self, idx)
|
||||||
|
|
||||||
def add(self, s):
|
# def add(self, s):
|
||||||
"""Add a string to the vector"""
|
# """Add a string to the vector"""
|
||||||
return _idaapi.qstrvec_t_add(self, s)
|
# return _idaapi.qstrvec_t_add(self, s)
|
||||||
|
|
||||||
|
|
||||||
def from_list(self, lst):
|
# def from_list(self, lst):
|
||||||
"""Populates the vector from a Python string list"""
|
# """Populates the vector from a Python string list"""
|
||||||
return _idaapi.qstrvec_t_from_list(self, lst)
|
# return _idaapi.qstrvec_t_from_list(self, lst)
|
||||||
|
|
||||||
|
|
||||||
def clear(self, qclear=False):
|
# def clear(self, qclear=False):
|
||||||
"""
|
# """
|
||||||
Clears all strings from the vector.
|
# Clears all strings from the vector.
|
||||||
@param qclear: Just reset the size but do not actually free the memory
|
# @param qclear: Just reset the size but do not actually free the memory
|
||||||
"""
|
# """
|
||||||
return _idaapi.qstrvec_t_clear(self, qclear)
|
# return _idaapi.qstrvec_t_clear(self, qclear)
|
||||||
|
|
||||||
|
|
||||||
def insert(self, idx, s):
|
# def insert(self, idx, s):
|
||||||
"""Insert a string into the vector"""
|
# """Insert a string into the vector"""
|
||||||
return _idaapi.qstrvec_t_insert(self, idx, s)
|
# return _idaapi.qstrvec_t_insert(self, idx, s)
|
||||||
|
|
||||||
|
|
||||||
def remove(self, idx):
|
# def remove(self, idx):
|
||||||
"""Removes a string from the vector"""
|
# """Removes a string from the vector"""
|
||||||
return _idaapi.qstrvec_t_remove(self, idx)
|
# return _idaapi.qstrvec_t_remove(self, idx)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
class PyIdc_cvt_refclass__(pyidc_cvt_helper__):
|
class PyIdc_cvt_refclass__(pyidc_cvt_helper__):
|
||||||
|
1111
swig/hexrays.i
Normal file
1111
swig/hexrays.i
Normal file
File diff suppressed because it is too large
Load Diff
103
swig/idaapi.i
103
swig/idaapi.i
@ -100,6 +100,9 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
|
|||||||
#include "fpro.h"
|
#include "fpro.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "graph.hpp"
|
#include "graph.hpp"
|
||||||
|
#ifdef WITH_HEXRAYS
|
||||||
|
#include "hexrays.hpp"
|
||||||
|
#endif
|
||||||
#include "pywraps.hpp"
|
#include "pywraps.hpp"
|
||||||
|
|
||||||
//<code(py_idaapi)>
|
//<code(py_idaapi)>
|
||||||
@ -2308,72 +2311,72 @@ class PyIdc_cvt_int64__(pyidc_cvt_helper__):
|
|||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
# qstrvec_t clinked object
|
# qstrvec_t clinked object
|
||||||
class qstrvec_t(py_clinked_object_t):
|
# class qstrvec_t(py_clinked_object_t):
|
||||||
"""Class representing an qstrvec_t"""
|
# """Class representing an qstrvec_t"""
|
||||||
|
|
||||||
def __init__(self, items=None):
|
# def __init__(self, items=None):
|
||||||
py_clinked_object_t.__init__(self)
|
# py_clinked_object_t.__init__(self)
|
||||||
# Populate the list if needed
|
# # Populate the list if needed
|
||||||
if items:
|
# if items:
|
||||||
self.from_list(items)
|
# self.from_list(items)
|
||||||
|
|
||||||
def _create_clink(self):
|
# def _create_clink(self):
|
||||||
return _idaapi.qstrvec_t_create()
|
# return _idaapi.qstrvec_t_create()
|
||||||
|
|
||||||
def _del_clink(self, lnk):
|
# def _del_clink(self, lnk):
|
||||||
return _idaapi.qstrvec_t_destroy(lnk)
|
# return _idaapi.qstrvec_t_destroy(lnk)
|
||||||
|
|
||||||
def _get_clink_ptr(self):
|
# def _get_clink_ptr(self):
|
||||||
return _idaapi.qstrvec_t_get_clink_ptr(self)
|
# return _idaapi.qstrvec_t_get_clink_ptr(self)
|
||||||
|
|
||||||
def assign(self, other):
|
# def assign(self, other):
|
||||||
"""Copies the contents of 'other' to 'self'"""
|
# """Copies the contents of 'other' to 'self'"""
|
||||||
return _idaapi.qstrvec_t_assign(self, other)
|
# return _idaapi.qstrvec_t_assign(self, other)
|
||||||
|
|
||||||
def __setitem__(self, idx, s):
|
# def __setitem__(self, idx, s):
|
||||||
"""Sets string at the given index"""
|
# """Sets string at the given index"""
|
||||||
return _idaapi.qstrvec_t_set(self, idx, s)
|
# return _idaapi.qstrvec_t_set(self, idx, s)
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
# def __getitem__(self, idx):
|
||||||
"""Gets the string at the given index"""
|
# """Gets the string at the given index"""
|
||||||
return _idaapi.qstrvec_t_get(self, idx)
|
# return _idaapi.qstrvec_t_get(self, idx)
|
||||||
|
|
||||||
def __get_size(self):
|
# def __get_size(self):
|
||||||
return _idaapi.qstrvec_t_size(self)
|
# return _idaapi.qstrvec_t_size(self)
|
||||||
|
|
||||||
size = property(__get_size)
|
# size = property(__get_size)
|
||||||
"""Returns the count of elements"""
|
# """Returns the count of elements"""
|
||||||
|
|
||||||
def addressof(self, idx):
|
# def addressof(self, idx):
|
||||||
"""Returns the address (as number) of the qstring at the given index"""
|
# """Returns the address (as number) of the qstring at the given index"""
|
||||||
return _idaapi.qstrvec_t_addressof(self, idx)
|
# return _idaapi.qstrvec_t_addressof(self, idx)
|
||||||
|
|
||||||
def add(self, s):
|
# def add(self, s):
|
||||||
"""Add a string to the vector"""
|
# """Add a string to the vector"""
|
||||||
return _idaapi.qstrvec_t_add(self, s)
|
# return _idaapi.qstrvec_t_add(self, s)
|
||||||
|
|
||||||
|
|
||||||
def from_list(self, lst):
|
# def from_list(self, lst):
|
||||||
"""Populates the vector from a Python string list"""
|
# """Populates the vector from a Python string list"""
|
||||||
return _idaapi.qstrvec_t_from_list(self, lst)
|
# return _idaapi.qstrvec_t_from_list(self, lst)
|
||||||
|
|
||||||
|
|
||||||
def clear(self, qclear=False):
|
# def clear(self, qclear=False):
|
||||||
"""
|
# """
|
||||||
Clears all strings from the vector.
|
# Clears all strings from the vector.
|
||||||
@param qclear: Just reset the size but do not actually free the memory
|
# @param qclear: Just reset the size but do not actually free the memory
|
||||||
"""
|
# """
|
||||||
return _idaapi.qstrvec_t_clear(self, qclear)
|
# return _idaapi.qstrvec_t_clear(self, qclear)
|
||||||
|
|
||||||
|
|
||||||
def insert(self, idx, s):
|
# def insert(self, idx, s):
|
||||||
"""Insert a string into the vector"""
|
# """Insert a string into the vector"""
|
||||||
return _idaapi.qstrvec_t_insert(self, idx, s)
|
# return _idaapi.qstrvec_t_insert(self, idx, s)
|
||||||
|
|
||||||
|
|
||||||
def remove(self, idx):
|
# def remove(self, idx):
|
||||||
"""Removes a string from the vector"""
|
# """Removes a string from the vector"""
|
||||||
return _idaapi.qstrvec_t_remove(self, idx)
|
# return _idaapi.qstrvec_t_remove(self, idx)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
class PyIdc_cvt_refclass__(pyidc_cvt_helper__):
|
class PyIdc_cvt_refclass__(pyidc_cvt_helper__):
|
||||||
@ -2677,6 +2680,9 @@ NW_REMOVE = 0x0010
|
|||||||
%include "fixup.i"
|
%include "fixup.i"
|
||||||
%include "frame.i"
|
%include "frame.i"
|
||||||
%include "funcs.i"
|
%include "funcs.i"
|
||||||
|
#ifdef WITH_HEXRAYS
|
||||||
|
%include "hexrays.i"
|
||||||
|
#endif
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
|
|
||||||
@ -2780,6 +2786,7 @@ def RunPythonStatement(stmt):
|
|||||||
#</pydoc>
|
#</pydoc>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// qstrvec_t wrapper
|
// qstrvec_t wrapper
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@ -2883,7 +2890,7 @@ static bool qstrvec_t_remove(PyObject *self, size_t idx)
|
|||||||
sv->erase(sv->begin()+idx);
|
sv->erase(sv->begin()+idx);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
47
swig/pro.i
47
swig/pro.i
@ -1,3 +1,21 @@
|
|||||||
|
//---------------------------------------------------------------------
|
||||||
|
%typemap(out) uint64 {
|
||||||
|
$result = PyLong_FromUnsignedLongLong((unsigned long long) $1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
%typemap(in) uint64
|
||||||
|
{
|
||||||
|
uint64 $1_temp;
|
||||||
|
if ( !PyW_GetNumber($input, &$1_temp) )
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "Expected an uint64 type");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
$1 = $1_temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
%ignore wchar2char;
|
%ignore wchar2char;
|
||||||
%ignore hit_counter_t;
|
%ignore hit_counter_t;
|
||||||
%ignore reg_hit_counter;
|
%ignore reg_hit_counter;
|
||||||
@ -6,10 +24,8 @@
|
|||||||
%ignore print_all_counters;
|
%ignore print_all_counters;
|
||||||
%ignore incrementer_t;
|
%ignore incrementer_t;
|
||||||
%ignore reloc_info_t; // swig under mac chokes on this
|
%ignore reloc_info_t; // swig under mac chokes on this
|
||||||
%ignore qstrvec_t;
|
|
||||||
%ignore qmutex_create;
|
%ignore qmutex_create;
|
||||||
%ignore qiterator;
|
%ignore qiterator;
|
||||||
%ignore qrefcnt_t;
|
|
||||||
%ignore qmutex_free;
|
%ignore qmutex_free;
|
||||||
%ignore qmutex_lock;
|
%ignore qmutex_lock;
|
||||||
%ignore qmutex_t;
|
%ignore qmutex_t;
|
||||||
@ -38,8 +54,6 @@
|
|||||||
%ignore qstrstr;
|
%ignore qstrstr;
|
||||||
%ignore qstrchr;
|
%ignore qstrchr;
|
||||||
%ignore qstrrchr;
|
%ignore qstrrchr;
|
||||||
%ignore qstring;
|
|
||||||
%ignore qvector;
|
|
||||||
%ignore bytevec_t;
|
%ignore bytevec_t;
|
||||||
%ignore reloc_info_t;
|
%ignore reloc_info_t;
|
||||||
%ignore relobj_t;
|
%ignore relobj_t;
|
||||||
@ -96,4 +110,27 @@
|
|||||||
%ignore qstrupr;
|
%ignore qstrupr;
|
||||||
%include "pro.h"
|
%include "pro.h"
|
||||||
|
|
||||||
SWIG_DECLARE_PY_CLINKED_OBJECT(qstrvec_t)
|
//---------------------------------------------------------------------
|
||||||
|
%template(uvalvec_t) qvector<uval_t>; // vector of unsigned values
|
||||||
|
%template(intvec_t) qvector<int>; // vector of integers
|
||||||
|
%template(qstrvec_t) qvector<qstring>; // vector of strings
|
||||||
|
%template(boolvec_t) qvector<bool>; // vector of bools
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
class qstring {
|
||||||
|
public:
|
||||||
|
const char *c_str() const { return self->c_str(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// for obscure reasons swig can't get past this one on its own, it needs a dummy declaration.
|
||||||
|
class strvec_t {
|
||||||
|
public:
|
||||||
|
qstring& at(int _idx) { return self->at(_idx).line; }
|
||||||
|
size_t size() const { return self->size(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class qtype {
|
||||||
|
public:
|
||||||
|
const uchar *c_str() const { return self->c_str(); }
|
||||||
|
};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//---------------------------------------------------------------------
|
||||||
// Convert an incoming Python list to a tid_t[] array
|
// Convert an incoming Python list to a tid_t[] array
|
||||||
%typemap(in) tid_t[ANY](tid_t temp[$1_dim0]) {
|
%typemap(in) tid_t[ANY](tid_t temp[$1_dim0]) {
|
||||||
int i, len;
|
int i, len;
|
||||||
@ -27,16 +28,21 @@
|
|||||||
$1 = &temp[0];
|
$1 = &temp[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
%define %cstring_output_maxstr_none(TYPEMAP, SIZE)
|
%define %cstring_output_maxstr_none(TYPEMAP, SIZE)
|
||||||
|
|
||||||
%typemap (default) SIZE {
|
%typemap (default) SIZE {
|
||||||
$1 = MAXSTR;
|
$1 = MAXSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
|
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
|
||||||
$1 = ($1_ltype) qalloc(MAXSTR+1);
|
$1 = ($1_ltype) qalloc(MAXSTR+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(out) ssize_t {
|
%typemap(out) ssize_t {
|
||||||
/* REMOVING ssize_t return value in $symname */
|
/* REMOVING ssize_t return value in $symname */
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(argout) (TYPEMAP,SIZE) {
|
%typemap(argout) (TYPEMAP,SIZE) {
|
||||||
if (result > 0)
|
if (result > 0)
|
||||||
{
|
{
|
||||||
@ -51,6 +57,7 @@
|
|||||||
}
|
}
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
%define %cstring_bounded_output_none(TYPEMAP,MAX)
|
%define %cstring_bounded_output_none(TYPEMAP,MAX)
|
||||||
%typemap(in, numinputs=0) TYPEMAP(char temp[MAX+1]) {
|
%typemap(in, numinputs=0) TYPEMAP(char temp[MAX+1]) {
|
||||||
$1 = ($1_ltype) temp;
|
$1 = ($1_ltype) temp;
|
||||||
@ -72,6 +79,7 @@
|
|||||||
}
|
}
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
%define %binary_output_or_none(TYPEMAP, SIZE)
|
%define %binary_output_or_none(TYPEMAP, SIZE)
|
||||||
%typemap (default) SIZE {
|
%typemap (default) SIZE {
|
||||||
$1 = MAXSPECSIZE;
|
$1 = MAXSPECSIZE;
|
||||||
@ -96,6 +104,7 @@
|
|||||||
}
|
}
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
%define %binary_output_with_size(TYPEMAP, SIZE)
|
%define %binary_output_with_size(TYPEMAP, SIZE)
|
||||||
%typemap (default) SIZE {
|
%typemap (default) SIZE {
|
||||||
size_t ressize = MAXSPECSIZE;
|
size_t ressize = MAXSPECSIZE;
|
||||||
@ -121,6 +130,7 @@
|
|||||||
}
|
}
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
// Check that the argument is a callable Python object
|
// Check that the argument is a callable Python object
|
||||||
%typemap(in) PyObject *pyfunc {
|
%typemap(in) PyObject *pyfunc {
|
||||||
if (!PyCallable_Check($input)) {
|
if (!PyCallable_Check($input)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user