...
  View open merge request
Commits (13)
......@@ -43,6 +43,7 @@ option(ENABLE_STATIC "Build static library." YES)
option(ENABLE_ADVANCED_IM "Enable advanced instant messaging such as group chat." YES)
option(ENABLE_CONSOLE_UI "Turn on or off compilation of console interface." YES)
option(ENABLE_CSHARP_WRAPPER "Build the C# wrapper for Liblinphone." OFF)
option(ENABLE_PYTHON_WRAPPER "Build the Python wrapper for Liblinphone." OFF)
option(ENABLE_CXX_WRAPPER "Build the C++ wrapper for Liblinphone." YES)
option(ENABLE_DB_STORAGE "Enable database storage." YES)
option(ENABLE_SWIFT_WRAPPER "Build the swift wrapper for Liblinphone." OFF)
......@@ -179,10 +180,13 @@ if(ENABLE_LIME)
find_package(bzrtp REQUIRED CONFIG)
set(HAVE_LIME 1)
endif()
if(ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER OR ENABLE_JAVA_WRAPPER OR ENABLE_SWIFT_WRAPPER OR ENABLE_DOC)
if(ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER OR ENABLE_JAVA_WRAPPER OR ENABLE_SWIFT_WRAPPER OR ENABLE_DOC OR ENABLE_PYTHON_WRAPPER)
find_package(PythonInterp REQUIRED)
check_python_module(pystache)
check_python_module(six)
if(ENABLE_PYTHON_WRAPPER)
check_python_module(cython)
endif()
if(ENABLE_DOC)
check_python_module(sphinx)
check_python_module(javasphinx)
......@@ -389,6 +393,9 @@ endif()
if(ENABLE_SWIFT_WRAPPER)
add_subdirectory(wrappers/swift)
endif()
if(ENABLE_PYTHON_WRAPPER)
add_subdirectory(wrappers/python)
endif()
include(CMakePackageConfigHelpers)
set(CONFIG_PACKAGE_LOCATION "${CMAKE_INSTALL_DATADIR}/Linphone/cmake")
......
......@@ -536,12 +536,16 @@ static const LinphoneAddress *_linphone_event_cache_remote_contact (const Linpho
return lev->remote_contact_address;
}
const LinphoneAddress *linphone_event_get_from (const LinphoneEvent *lev) {
const LinphoneAddress *linphone_event_get_from_address (const LinphoneEvent *lev) {
if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing)
return _linphone_event_cache_to(lev);
return _linphone_event_cache_from(lev);
}
const LinphoneAddress *linphone_event_get_from (const LinphoneEvent *lev) {
return linphone_event_get_from_address(lev);
}
const LinphoneAddress *linphone_event_get_resource(const LinphoneEvent *lev){
if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing)
return _linphone_event_cache_from(lev);
......
......@@ -20,7 +20,7 @@
#
################################################################################
if(ENABLE_DOC OR ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER OR ENABLE_JAVA_WRAPPER OR ENABLE_SWIFT_WRAPPER)
if(ENABLE_DOC OR ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER OR ENABLE_JAVA_WRAPPER OR ENABLE_SWIFT_WRAPPER OR ENABLE_PYTHON_WRAPPER)
find_package(Doxygen REQUIRED)
if(DOXYGEN_FOUND)
set(top_srcdir "${PROJECT_SOURCE_DIR}")
......
......@@ -172,7 +172,8 @@ class LangInfo:
'Cpp' : 'C++',
'Java' : 'Java',
'CSharp': 'C#',
'Swift' : 'Swift'
'Swift' : 'Swift',
'Python': 'Python'
}
......@@ -457,8 +458,9 @@ class DocGenerator:
LangInfo('C'),
LangInfo('Cpp'),
LangInfo('Java'),
LangInfo('CSharp')#,
#LangInfo('Swift')
LangInfo('CSharp'),
#LangInfo('Swift'),
LangInfo('Python')
]
def generate(self, outputdir):
......
......@@ -184,9 +184,15 @@ LINPHONE_PUBLIC const char *linphone_event_get_name(const LinphoneEvent *lev);
/**
* Get the "from" address of the subscription.
* @deprecated use linphone_event_get_from_address instead
**/
LINPHONE_PUBLIC const LinphoneAddress *linphone_event_get_from(const LinphoneEvent *lev);
/**
* Get the "from" address of the subscription.
**/
LINPHONE_PUBLIC const LinphoneAddress *linphone_event_get_from_address(const LinphoneEvent *lev);
/**
* Get the resource address of the subscription or publish.
**/
......
......@@ -1471,3 +1471,37 @@ class CSharpLangTranslator(CLikeLangTranslator):
name = method.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)),
args = ', '.join([arg.translate(self, dllImport=False, namespace=namespace) for arg in method.args]) if not hideArguments else ''
)
class PythonLangTranslator(CLikeLangTranslator):
def __init__(self):
self.nameTranslator = metaname.Translator.get('Python')
self.nilToken = 'None'
self.falseConstantToken = 'False'
self.trueConstantToken = 'True'
def translate_base_type(self, _ctype):
_type = _ctype.name
if _ctype.name == 'boolean':
_type = 'bint'
elif _ctype.name == 'integer':
_type = 'int'
elif _ctype.name == 'floatant':
_type = 'float'
elif _ctype.name == 'size':
_type = 'size_t'
elif _ctype.name == 'status':
_type = 'bint'
elif _ctype.name == 'string':
_type = 'char*'
elif _ctype.name == 'character':
_type = 'char'
elif _ctype.name == 'time':
_type = 'time_t'
if _ctype.isUnsigned:
_type = 'unsigned ' + _type
if _ctype.isconst:
_type = 'const ' + _type
if _ctype.isref:
_type += '*'
return _type
\ No newline at end of file
......@@ -636,6 +636,15 @@ class SphinxTranslator(Translator):
self.methodDeclarator = 'class_method'
self.enumDeclarator = 'enum'
self.enumeratorDeclarator = 'enum_case'
elif langCode == 'Python':
self.domain = 'python'
self.classDeclarator = 'class'
self.interfaceDeclarator = self.classDeclarator
self.methodDeclarator = 'method'
self.enumDeclarator = 'type'
self.enumeratorDeclarator = 'field'
self.namespaceDeclarator = 'package'
self.methodReferencer = 'meth'
else:
raise ValueError('invalid language code: {0}'.format(langCode))
......@@ -742,3 +751,15 @@ class SandCastleTranslator(Translator):
def translate_class_reference(self, ref):
refStr = Translator.translate_reference(self, ref, absName=True)
return '<see cref="{0}" />'.format(refStr)
class PythonTranslator(Translator):
def _tag_as_brief(self, lines):
pass
def translate_function_reference(self, ref):
refStr = Translator.translate_reference(self, ref, absName=True)
return refStr
def translate_class_reference(self, ref):
refStr = Translator.translate_reference(self, ref, absName=True)
return refStr
......@@ -370,3 +370,26 @@ class CSharpTranslator(JavaTranslator):
def translate_property_name(self, name):
return name.to_camel_case()
class PythonTranslator(JavaTranslator):
def __init__(self):
JavaTranslator.__init__(self)
self.keyWordEscapes = {
'type' : '_type',
'file' : '_file',
'list' : '_list',
'from' : '_from',
'id' : '_id',
'filter' : '_filter',
'dir' : '_dir',
'max' : '_max',
'min' : '_min',
'range' : '_range',
}
self.lowerMethodNames = True
self.lowerNamespaceNames = False
def translate_arg_name(self, name):
if name in self.keyWordEscapes:
return '_' + name
return name
\ No newline at end of file
############################################################################
# CMakeLists.txt
# Copyright (C) 2019 Belledonne Communications, Grenoble France
#
############################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
############################################################################
configure_file("setup.cmake" "setup.py" @ONLY)
add_custom_command(OUTPUT pylinphone.pyx
COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/genwrapper.py" "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml"
DEPENDS ${PROJECT_SOURCE_DIR}/tools/genapixml.py
${PROJECT_SOURCE_DIR}/tools/metadoc.py
${PROJECT_SOURCE_DIR}/tools/abstractapi.py
genwrapper.py
pylinphone.mustache
linphone-doc
)
add_custom_command(OUTPUT pylinphone.so
COMMAND ${PYTHON_EXECUTABLE} setup.py build_ext --inplace
DEPENDS pylinphone.pyx
)
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/linphone" DESTINATION .)
add_custom_command(OUTPUT pylinphone*.whl
COMMAND ${PYTHON_EXECUTABLE} setup.py bdist_wheel --dist-dir ${CMAKE_INSTALL_PREFIX}/
DEPENDS pylinphone.so
)
add_custom_target(pylinphone ALL DEPENDS pylinphone.pyx pylinphone.so pylinphone*.whl)
add_custom_command(TARGET pylinphone
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/*" "./linphone/"
COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_BINARY_DIR}/src/liblinphone.so" "./linphone/"
)
add_dependencies(pylinphone linphone)
\ No newline at end of file
This diff is collapsed.
import os
from ctypes import CDLL
lib_path = os.path.join(os.path.dirname(__file__), 'liblinphone.so')
liblinphone_library = CDLL(lib_path)
from pylinphone import *
\ No newline at end of file
This diff is collapsed.
import linphone
print(linphone.Core.get_version())
from setuptools import setup, Distribution
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
linphone_extension = Extension(
name="pylinphone",
sources=["pylinphone.pyx"],
libraries=["linphone"],
language="c",
library_dirs=["@PROJECT_BINARY_DIR@/src"],
include_dirs=["@PROJECT_SOURCE_DIR@/include", "@BELLESIP_INCLUDE_DIRS@", "@BCTOOLBOX_INCLUDE_DIRS@"]
)
class BinaryDistribution(Distribution):
def has_ext_modules(self):
return True
def is_pure(self):
return False
setup(
ext_modules = cythonize([linphone_extension]),
name="pylinphone",
version="@LINPHONESDK_VERSION@",
author="Belledonne Communications",
author_email="info@belledonne-communications.com",
description="A python wrapper for linphone library",
long_description="A python wrapper for linphone library automatically generated using pyrex",
long_description_content_type="plain/text",
url="https://linphone.org",
license="GPLv2",
packages=['linphone'],
package_data={'linphone': ['*.so']},
distclass=BinaryDistribution
)