{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "jna_demo.ipynb", "provenance": [], "collapsed_sections": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "A_qpcAZLM8H1" }, "source": [ "# ctypes로 Python에서 C++ 클래스 호출하기" ] }, { "cell_type": "markdown", "metadata": { "id": "fr8BoFCEpNZ-" }, "source": [ "* 원출처\n", " - https://www.auctoris.co.uk/2017/04/29/calling-c-classes-from-python-with-ctypes/#comments\n", "* 2차 번역\n", " - https://sdr1982.tistory.com/212" ] }, { "cell_type": "markdown", "metadata": { "id": "7zD_6AwnphCL" }, "source": [ "저는 파이썬에서 C++ 클래스를 호출하고 싶어서 최근에 스스로 방법을 찾았습니다. 저는 (Thrift를 사용하여 전에 했던 것처럼 - [Python과 C++을 위한 Apache Thrift 사용하기](https://www.auctoris.co.uk/2016/08/17/using-apache-thrift-for-python-c/)를 보세요.) 분리된 프로세스 를 호출하고 싶지 않았고 C++ 라이브러리를 직접 호출하고 싶었습니다.\n", "\n", "저는 진행하기 전에 이를 Java로 하기 위한 다양한 방법이 있다는 것을 말하고 싶습니다. 그리고 저는 작동한 것 중 하나를 선택하였습니다. 다른 기술도 사용 가능하며 어떤 기술이 '최상'인지에 대한 의견은 상당히 분분해 보입니다.\n", "\n", "C++ 클래스로 시작하기 위해 평범하게 작성하였습니다." ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "BLastn_3phdB", "outputId": "28e7d2f3-ce16-4138-9c3e-8e537c9b948b" }, "source": [ "%%writefile foo.cpp\n", "#include \n", "\n", "// A simple class with a constuctor and some methods...\n", "// 생성자와 몇 개의 메소드를 가지는 간단한 클래스...\n", "\n", "class Foo\n", "{\n", " public:\n", " Foo(int);\n", " void bar();\n", " int foobar(int);\n", " private:\n", " int val;\n", "};\n", "\n", "Foo::Foo(int n)\n", "{\n", " val = n;\n", "}\n", "\n", "void Foo::bar()\n", "{\n", " std::cout << \"Value is \" << val << std::endl;\n", "}\n", "\n", "int Foo::foobar(int n)\n", "{\n", " return val + n;\n", "}" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "Writing foo.cpp\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "Y1MZsC6np-mc" }, "source": [ "다음 ctypes 시스템은 C++을 사용할 수 없기 때문에 C++ 코드 주변에 C wrapper를 놓을 것입니다. 이를 하기 위해 파일 제일 밑에 다음 부분에 코드를 추가합니다." ] }, { "cell_type": "code", "metadata": { "id": "tB5Ov9Tjp3li" }, "source": [ "add_src = \"\"\"\n", "\n", "extern \"C\"\n", "{\n", " Foo* Foo_new(int n) {return new Foo(n);}\n", " void Foo_bar(Foo* foo) {foo->bar();}\n", " int Foo_foobar(Foo* foo, int n) {return foo->foobar(n);}\n", "}\"\"\"\n", "\n", "f = open('foo.cpp', 'a')\n", "f.write(add_src)\n", "f.close()" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "9auglH5pqSIy" }, "source": [ "호출하기 원하는 각 메소드를 클래스 기반이 아닌 이름으로 제공해야 함을 알아두세요.\n", "\n", "우리는 우리 코드에서 libfoo.so 파일을 빌드해야 합니다.\n", "\n", "다음을 쉘에서 입력하세요." ] }, { "cell_type": "code", "metadata": { "id": "nLsXm4YCqOZc" }, "source": [ "!g++ -c -fPIC foo.cpp -o foo.o" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": { "id": "pDAWiOIEqVuy" }, "source": [ "!g++ -shared -Wl,-soname,libfoo.so -o libfoo.so foo.o" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "wSkzcIn3rAYt", "outputId": "978b9f23-652b-4e49-960f-096aca0da144" }, "source": [ "!ls -lrt" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "total 32\n", "drwxr-xr-x 1 root root 4096 May 6 13:44 sample_data\n", "-rw-r--r-- 1 root root 586 May 20 08:43 foo.cpp\n", "-rw-r--r-- 1 root root 4424 May 20 08:44 foo.o\n", "-rwxr-xr-x 1 root root 13320 May 20 08:44 libfoo.so\n" ], "name": "stdout" } ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "DBqlcYjfsSel", "outputId": "a44245e5-ed20-4e9e-e886-e6667802f61a" }, "source": [ "!cat foo.cpp" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "#include \n", "\n", "// A simple class with a constuctor and some methods...\n", "// 생성자와 몇 개의 메소드를 가지는 간단한 클래스...\n", "\n", "class Foo\n", "{\n", " public:\n", " Foo(int);\n", " void bar();\n", " int foobar(int);\n", " private:\n", " int val;\n", "};\n", "\n", "Foo::Foo(int n)\n", "{\n", " val = n;\n", "}\n", "\n", "void Foo::bar()\n", "{\n", " std::cout << \"Value is \" << val << std::endl;\n", "}\n", "\n", "int Foo::foobar(int n)\n", "{\n", " return val + n;\n", "}\n", "\n", "extern \"C\"\n", "{\n", " Foo* Foo_new(int n) {return new Foo(n);}\n", " void Foo_bar(Foo* foo) {foo->bar();}\n", " int Foo_foobar(Foo* foo, int n) {return foo->foobar(n);}\n", "}" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "Nn6dGfUcrZdC" }, "source": [ "또는 CMake를 사용할 수 있습니다.\n", "\n", "다음은 foo.cpp를 빌드하기 위한 CMakeLists.txt 입니다.\n", "\n", "```\n", "cmake_minimum_required(VERSION 2.8.9)\n", "set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++11 -Wall\")\n", "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"${CMAKE_SOURCE_DIR}\")\n", "set(CMAKE_MACOSX_RPATH 1)\n", "\n", "project (foo)\n", "set (SOURCE foo.cpp)\n", "add_library(foo MODULE ${SOURCE}) \n", "```" ] }, { "cell_type": "markdown", "metadata": { "id": "M04EsLIarmZi" }, "source": [ "저는 Mac에서 빌드를 해서 MacOS를 위해 4번째 줄을 추가하였습니다. 리눅스에서도 잘 작동하겠지만 필요는 없습니다.\n", "\n", "이제 C++로 컴파일 된 내용을 작성합니다. 우리는 클래스에 대한 Python wrapper를 빌드하려 합니다." ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "bKl9pbkJrRb0", "outputId": "7de145b2-571b-4b22-b220-33a77d232f6b" }, "source": [ "%%writefile foo.py\n", "import ctypes\n", "\n", "lib = ctypes.cdll.LoadLibrary('./libfoo.so')\n", "\n", "class Foo(object):\n", " def __init__(self, val):\n", " lib.Foo_new.argtypes = [ctypes.c_int]\n", " lib.Foo_new.restype = ctypes.c_void_p\n", "\n", " lib.Foo_bar.argtypes = [ctypes.c_void_p]\n", " lib.Foo_bar.restype = ctypes.c_void_p\n", "\n", " lib.Foo_foobar.argtypes = [ctypes.c_void_p, ctypes.c_int]\n", " lib.Foo_foobar.restype = ctypes.c_int\n", "\n", " self.obj = lib.Foo_new(val)\n", " \n", " def bar(self):\n", " lib.Foo_bar(self.obj)\n", " \n", " def foobar(self, val):\n", " return lib.Foo_foobar(self.obj, val)" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "Writing foo.py\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "2CjAVMbvr0ui" }, "source": [ "리턴 값의 타입과 argument 타입을 정의하는 요구사항을 적으세요. (하나도 리턴하지 않으면 예시로 void를 리턴합니다.) 이것이 없으면 segmentation fault(등)를 얻을 것입니다.\n", "\n", "이제 모든 것을 다 하였고 모듈을 빌드해야 합니다. 파이썬에서 간단히 그것을 import할 수 있습니다.\n", "\n", "예를 들어\n", "\n", "```python\n", "from foo import Foo\n", "# 우리는 5라는 값으로 Foo 객체를 생성할 것입니다...\n", "f=Foo(5)\n", "# f.bar()를 호출하는 것은 값을 포함한 메시지를 출력할 것입니다...\n", "f.bar()\n", "# 이제 f, Foo 객체에서 저장되어 있는 값에 값(7)을 더하기 위해 foobar를 사용합니다.\n", "print (f.foobar(7))\n", "# 또 한 번 같은 메소드를 호출합니다 - 이 번엔 일반적인 파이썬 정수를 \n", "# 보여줄 것입니다...\n", "x = f.foobar(2)\n", "print (type(x))\n", "```" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "gycYGji8rz6R", "outputId": "ec1082ce-cf8a-4568-e220-5c3e2f7d9bd1" }, "source": [ "!python" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "Python 3.7.10 (default, May 3 2021, 02:48:31) \n", "[GCC 7.5.0] on linux\n", "Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n", ">>> from foo import Foo\n", ">>> f=Foo(5)\n", ">>> f.bar()\n", "Value is 5\n", ">>> print (f.foobar(7))\n", "12\n", ">>> x = f.foobar(2)\n", ">>> x\n", "7\n", ">>> print (type(x))\n", "\n", ">>> quit()\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "wScADZHavCFo" }, "source": [ "이 간단한 데모를 위한 전체 소스 코드는 여기에 있습니다.\n", "\n", "https://github.com/Auctoris/ctypes_demo" ] }, { "cell_type": "markdown", "metadata": { "id": "h4WBKHbauhyV" }, "source": [ "# JNA로 Java에서 C++ 클래스 호출하기" ] }, { "cell_type": "markdown", "metadata": { "id": "kVztqSQ-w2aU" }, "source": [ "## 사전작업" ] }, { "cell_type": "markdown", "metadata": { "id": "qJCl9hGozEZ8" }, "source": [ "* java 설치(Java 8 다운그레이드)" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "16aMmvCBzHdU", "outputId": "79d0099e-5d77-42d6-f85e-9a6fb57dbb9c" }, "source": [ "!apt-get update\n", "!apt-get install openjdk-8-jdk-headless -qq > /dev/null" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "\r0% [Working]\r \rHit:1 http://archive.ubuntu.com/ubuntu bionic InRelease\n", "\r0% [Waiting for headers] [Connecting to security.ubuntu.com (91.189.91.39)] [Co\r \rGet:2 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]\n", "\r \rGet:3 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic InRelease [15.9 kB]\n", "\r \rHit:4 http://ppa.launchpad.net/cran/libgit2/ubuntu bionic InRelease\n", "\r0% [Waiting for headers] [Connecting to security.ubuntu.com (91.189.91.39)] [Wa\r0% [1 InRelease gpgv 242 kB] [Waiting for headers] [Connecting to security.ubun\r \rGet:5 https://cloud.r-project.org/bin/linux/ubuntu bionic-cran40/ InRelease [3,626 B]\n", "\r0% [1 InRelease gpgv 242 kB] [Waiting for headers] [Connecting to security.ubun\r \rGet:6 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]\n", "\r0% [1 InRelease gpgv 242 kB] [6 InRelease 11.3 kB/74.6 kB 15%] [Connecting to s\r0% [1 InRelease gpgv 242 kB] [Connecting to security.ubuntu.com (91.189.91.39)]\r \rHit:7 http://ppa.launchpad.net/deadsnakes/ppa/ubuntu bionic InRelease\n", "\r0% [1 InRelease gpgv 242 kB] [Connecting to security.ubuntu.com (91.189.91.39)]\r \rGet:8 http://ppa.launchpad.net/graphics-drivers/ppa/ubuntu bionic InRelease [21.3 kB]\n", "Get:9 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]\n", "Ign:10 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease\n", "Ign:11 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 InRelease\n", "Get:12 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 Release [697 B]\n", "Hit:13 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 Release\n", "Get:14 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 Release.gpg [836 B]\n", "Get:15 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [2,183 kB]\n", "Get:16 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [2,583 kB]\n", "Get:17 http://archive.ubuntu.com/ubuntu bionic-updates/restricted amd64 Packages [452 kB]\n", "Get:18 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic/main Sources [1,767 kB]\n", "Get:19 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic/main amd64 Packages [904 kB]\n", "Get:20 https://cloud.r-project.org/bin/linux/ubuntu bionic-cran40/ Packages [60.5 kB]\n", "Get:21 http://ppa.launchpad.net/graphics-drivers/ppa/ubuntu bionic/main amd64 Packages [41.5 kB]\n", "Ign:23 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 Packages\n", "Get:23 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 Packages [772 kB]\n", "Get:24 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [2,152 kB]\n", "Get:25 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [1,412 kB]\n", "Get:26 http://security.ubuntu.com/ubuntu bionic-security/restricted amd64 Packages [423 kB]\n", "Fetched 13.0 MB in 4s (3,488 kB/s)\n", "Reading package lists... Done\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "aMU90zT1zQB8" }, "source": [ "* Java 환경변수 설정" ] }, { "cell_type": "code", "metadata": { "id": "Hm1XoZlfzRTD" }, "source": [ "import os\n", "os.environ[\"JAVA_HOME\"] = \"/usr/lib/jvm/java-8-openjdk-amd64\"\n", "os.environ[\"PATH\"] = \"/usr/lib/jvm/java-8-openjdk-amd64/bin:\" + os.environ[\"PATH\"]" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "3vdIiSGQzWbM" }, "source": [ "* Java 버전 확인.\n", " - Java 8 버전인지 확인.\n", " - 설치할 Gradle과 호환성을 맞추기 위해 Java 다운그레이드" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "8dbKZHPEzeNY", "outputId": "61c71b87-a849-4ef9-8e70-de11633f5c38" }, "source": [ "!java -version" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "openjdk version \"1.8.0_292\"\n", "OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~18.04-b10)\n", "OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "6318aXgszK90" }, "source": [ "* gradle 설치\n", " - https://yallalabs.com/devops/how-to-install-gradle-ubuntu-18-04-ubuntu-16-04/" ] }, { "cell_type": "markdown", "metadata": { "id": "f36yBTJZ18Op" }, "source": [ "* Gradle 다운로드\n", " - 3.4.1 버전의 **Gradle**을 받기 위해 다음처럼 진행." ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "3k5KJmoNw7B6", "outputId": "431737e6-d361-4082-b681-c25bb3f0a360" }, "source": [ "!wget https://services.gradle.org/distributions/gradle-3.4.1-bin.zip -P /tmp" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "--2021-05-20 08:55:53-- https://services.gradle.org/distributions/gradle-3.4.1-bin.zip\n", "Resolving services.gradle.org (services.gradle.org)... 104.18.191.9, 104.18.190.9, 2606:4700::6812:be09, ...\n", "Connecting to services.gradle.org (services.gradle.org)|104.18.191.9|:443... connected.\n", "HTTP request sent, awaiting response... 301 Moved Permanently\n", "Location: https://downloads.gradle-dn.com/distributions/gradle-3.4.1-bin.zip [following]\n", "--2021-05-20 08:55:53-- https://downloads.gradle-dn.com/distributions/gradle-3.4.1-bin.zip\n", "Resolving downloads.gradle-dn.com (downloads.gradle-dn.com)... 104.18.165.99, 104.18.164.99, 2606:4700::6812:a563, ...\n", "Connecting to downloads.gradle-dn.com (downloads.gradle-dn.com)|104.18.165.99|:443... connected.\n", "HTTP request sent, awaiting response... 200 OK\n", "Length: 70310446 (67M) [application/zip]\n", "Saving to: ‘/tmp/gradle-3.4.1-bin.zip’\n", "\n", "gradle-3.4.1-bin.zi 100%[===================>] 67.05M 177MB/s in 0.4s \n", "\n", "2021-05-20 08:55:53 (177 MB/s) - ‘/tmp/gradle-3.4.1-bin.zip’ saved [70310446/70310446]\n", "\n" ], "name": "stdout" } ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "vCsZWO6xxG4-", "outputId": "29f3d98b-b58e-408f-9ba9-7ee29c84ba27" }, "source": [ "!sudo unzip -d /opt/gradle /tmp/gradle-*.zip" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "Archive: /tmp/gradle-3.4.1-bin.zip\n", " creating: /opt/gradle/gradle-3.4.1/\n", " inflating: /opt/gradle/gradle-3.4.1/LICENSE \n", " creating: /opt/gradle/gradle-3.4.1/media/\n", " inflating: /opt/gradle/gradle-3.4.1/media/gradle-icon-16x16.png \n", " inflating: /opt/gradle/gradle-3.4.1/media/gradle-icon-24x24.png \n", " inflating: /opt/gradle/gradle-3.4.1/media/gradle.icns \n", " inflating: /opt/gradle/gradle-3.4.1/media/gradle-icon-512x512.png \n", " inflating: /opt/gradle/gradle-3.4.1/media/gradle-icon-32x32.png \n", " inflating: /opt/gradle/gradle-3.4.1/media/gradle-icon-128x128.png \n", " inflating: /opt/gradle/gradle-3.4.1/media/gradle-icon-64x64.png \n", " inflating: /opt/gradle/gradle-3.4.1/media/gradle-icon-256x256.png \n", " inflating: /opt/gradle/gradle-3.4.1/media/gradle-icon-48x48.png \n", " creating: /opt/gradle/gradle-3.4.1/init.d/\n", " inflating: /opt/gradle/gradle-3.4.1/init.d/readme.txt \n", " inflating: /opt/gradle/gradle-3.4.1/NOTICE \n", " inflating: /opt/gradle/gradle-3.4.1/getting-started.html \n", " creating: /opt/gradle/gradle-3.4.1/bin/\n", " inflating: /opt/gradle/gradle-3.4.1/bin/gradle.bat \n", " inflating: /opt/gradle/gradle-3.4.1/bin/gradle \n", " creating: /opt/gradle/gradle-3.4.1/lib/\n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-script-kotlin-0.5.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/kotlin-compiler-embeddable-1.1-M02.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/kotlin-reflect-1.1-M02.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/kotlin-runtime-1.1-M02.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/kotlin-stdlib-1.1-M02.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-launcher-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-wrapper-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-installation-beacon-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-base-services-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-jvm-services-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-core-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-cli-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-ui-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-tooling-api-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-native-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-logging-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/slf4j-api-1.7.10.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/guava-jdk5-17.0.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/commons-lang-2.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-process-services-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/groovy-all-2.4.7.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-model-core-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-model-groovy-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/asm-all-5.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/ant-1.9.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/commons-collections-3.2.2.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/commons-io-2.2.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/jcip-annotations-1.0.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/javax.inject-1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-base-services-groovy-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-messaging-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-resources-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-docs-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-open-api-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/dom4j-1.6.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/jaxen-1.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/jansi-1.14.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/jul-to-slf4j-1.7.10.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/log4j-over-slf4j-1.7.10.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/jcl-over-slf4j-1.7.10.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/ant-launcher-1.9.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/kryo-2.20.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-freebsd-amd64-libcpp-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-freebsd-amd64-libstdcpp-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-freebsd-i386-libcpp-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-freebsd-i386-libstdcpp-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-linux-amd64-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-linux-i386-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-osx-amd64-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-osx-i386-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-windows-amd64-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-windows-i386-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-linux-amd64-ncurses5-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-linux-amd64-ncurses6-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-linux-i386-ncurses5-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/native-platform-linux-i386-ncurses6-0.13.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/reflectasm-1.07-shaded.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/minlog-1.2.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/objenesis-1.2.jar \n", " creating: /opt/gradle/gradle-3.4.1/lib/plugins/\n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-plugins-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-code-quality-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-jetty-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-antlr-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-osgi-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-maven-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-ide-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-announce-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-scala-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-signing-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-ear-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-javascript-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-build-comparison-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-diagnostics-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-reporting-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-publish-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-ivy-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-jacoco-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-build-init-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-platform-base-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-platform-jvm-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-language-jvm-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-language-java-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-language-groovy-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-language-scala-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-platform-native-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-platform-play-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-ide-play-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-language-native-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-ide-native-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-testing-base-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-testing-native-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-testing-jvm-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-plugin-development-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-plugin-use-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-resources-http-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-resources-sftp-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-resources-s3-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-tooling-api-builders-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-composite-builds-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-build-cache-http-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-workers-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-dependency-management-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gradle-test-kit-3.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/commons-cli-1.2.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jetty-6.1.26.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jetty-util-6.1.26.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/servlet-api-2.5-20081211.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jetty-plus-6.1.26.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jsp-2.1-6.1.14.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jetty-annotations-6.1.26.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/geronimo-annotation_1.0_spec-1.0.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/biz.aQute.bndlib-3.2.0.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/maven-core-3.0.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/pmaven-common-0.8-20100325.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/pmaven-groovy-0.8-20100325.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/commons-codec-1.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/bcpg-jdk15on-1.51.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/rhino-1.7R3.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/gson-2.7.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/simple-4.1.21.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jatl-0.2.2.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/junit-4.12.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/testng-6.3.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/httpclient-4.4.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/nekohtml-1.9.14.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jsch-0.1.53.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/aws-java-sdk-s3-1.11.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/aws-java-sdk-kms-1.11.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/aws-java-sdk-core-1.11.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jackson-core-2.6.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jackson-annotations-2.6.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jackson-databind-2.6.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/joda-time-2.8.2.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/ivy-2.2.0.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/xbean-reflect-3.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/bcprov-jdk15on-1.51.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jetty-naming-6.1.26.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/core-3.1.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jsp-api-2.1-6.1.14.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/maven-settings-3.0.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/maven-settings-builder-3.0.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/plexus-utils-2.0.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/plexus-interpolation-1.14.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/plexus-container-default-1.5.5.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/plexus-classworlds-2.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/plexus-cipher-1.7.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/plexus-sec-dispatcher-1.3.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/maven-compat-3.0.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/maven-model-builder-3.0.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/maven-model-3.0.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/maven-artifact-3.0.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/maven-repository-metadata-3.0.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/maven-plugin-api-3.0.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/maven-aether-provider-3.0.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/wagon-file-2.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/wagon-http-2.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/wagon-provider-api-2.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/wagon-http-shared4-2.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/aether-api-1.13.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/aether-impl-1.13.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/aether-spi-1.13.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/aether-util-1.13.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/aether-connector-wagon-1.13.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/bsh-2.0b4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jcommander-1.12.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/snakeyaml-1.6.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/httpcore-4.4.4.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/jcifs-1.3.17.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/xercesImpl-2.9.1.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/xml-apis-1.3.04.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/plexus-component-annotations-1.5.5.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/plugins/hamcrest-core-1.3.jar \n", " inflating: /opt/gradle/gradle-3.4.1/lib/gradle-version-info-3.4.1.jar \n" ], "name": "stdout" } ] }, { "cell_type": "code", "metadata": { "id": "stOWL7xixna-" }, "source": [ "import os\n", "os.environ[\"GRADLE_HOME\"] = \"/opt/gradle/gradle-3.4.1\"\n", "os.environ[\"PATH\"] = \"/opt/gradle/gradle-3.4.1/bin:\" + os.environ[\"PATH\"]" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "gvAR_L_oxzTS" }, "source": [ "* gradle version 확인." ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "IpCR8ldExzr7", "outputId": "b7d37002-f421-4c67-b294-39c53b8e8cca" }, "source": [ "!gradle -v" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "\u001b[m\n", "------------------------------------------------------------\n", "Gradle 3.4.1\n", "------------------------------------------------------------\n", "\n", "Build time: 2017-03-03 19:45:41 UTC\n", "Revision: 9eb76efdd3d034dc506c719dac2955efb5ff9a93\n", "\n", "Groovy: 2.4.7\n", "Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015\n", "JVM: 1.8.0_292 (Private Build 25.292-b10)\n", "OS: Linux 5.4.109+ amd64\n", "\n", "\u001b[m" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "9R60YKk0unl-" }, "source": [ "* 출처 및 응용\n", " - http://www.auctoris.co.uk/2017/04/29/calling-c-classes-from-python-with-ctypes/#comments\n", " - https://sdr1982.tistory.com/263" ] }, { "cell_type": "markdown", "metadata": { "id": "aAF7mEIkurVz" }, "source": [ "저는 Java에서 C++ 클래스를 호출하고 싶어서 최근에 스스로 방법을 찾았습니다. 저는 C++ 라이브러리를 직접 호출하고 싶었습니다.\n", "\n", "저는 진행하기 전에 이를 Java로 하기 위한 다양한 방법이 있다는 것을 말하고 싶습니다. 그리고 저는 작동한 것 중 하나를 선택하였습니다. 다른 기술도 사용 가능하며 어떤 기술이 '최상'인지에 대한 의견은 상당히 분분해 보입니다.\n", "\n", "C++ 클래스로 시작하기 위해 평범하게 작성하였습니다." ] }, { "cell_type": "markdown", "metadata": { "id": "a_sZTUD9GMIb" }, "source": [ "```c++\n", "#include \n", "// A simple class with a constuctor and some methods... \n", "// 생성자와 몇 개의 메소드를 가지는 간단한 클래스... \n", "class Foo { \n", " public: \n", " Foo(int); \n", " void bar(); \n", " int foobar(int); \n", " private: \n", " int val; \n", "}; \n", "Foo::Foo(int n) { \n", " val = n; \n", "} \n", "void Foo::bar() { \n", " std::cout << \"Value is \" << val << std::endl; \n", "} \n", "int Foo::foobar(int n) { \n", " return val + n; \n", "}\n", "```" ] }, { "cell_type": "markdown", "metadata": { "id": "MLJvzk5lG_5o" }, "source": [ "JNA에서는 C++을 사용할 수 없기 때문에 C++ 코드 주변에 C wrapper를 놓을 것입니다. 이를 하기 위해 파일 제일 밑에 다음 부분에 코드를 추가합니다." ] }, { "cell_type": "markdown", "metadata": { "id": "xwuP-FryHBSL" }, "source": [ "```c++\n", "// ctypes는 C와만 대화할 수 있기 때문에 C++ 클래스를 위한 C 함수를 정의합니다. \n", "extern \"C\" { \n", " Foo* Foo_new(int n) { return new Foo(n); } \n", " void Foo_bar(Foo* foo) { foo->bar(); } \n", " int Foo_foobar(Foo* foo, int n) { return foo->foobar(n); } \n", "}\n", "```" ] }, { "cell_type": "markdown", "metadata": { "id": "frSILdyBH82L" }, "source": [ "호출하기 원하는 각 메소드를 클래스 기반이 아닌 이름으로 제공해야 함을 알아두세요.\n", "\n", "우리는 우리 코드에서 libfoo.so 파일을 빌드해야 합니다.\n", "\n", "다음을 쉘에서 입력하세요.\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "716X2-eWIE6s" }, "source": [ "```shell\n", "$ g++ -c -fPIC foo.cpp -o foo.o \n", "$ g++ -shared -W1,-soname,libfoo.so -o libfoo.so foo.o\n", "```\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "PvxfV7WpJeB_" }, "source": [ "gradle에서 JNA를 fat-jar로 컴파일하기 위해 빌드 스크립트를 만들었습니다.\n", "\n", "gradle 3.4.1에서 잘 작동함을 확인하였습니다.\n", "\n", "* fat-jar : 실행에 필요한 모든 라이브러리 class 파일을 하나의 jar 파일로 만듬.(빌드)" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "E7BESwpQsaMx", "outputId": "466e92b6-16ea-4b5a-851a-11b7a2e218f8" }, "source": [ "%%writefile build.gradle\n", "// Java 프로그램을 위한 기능을 제공하는 플러그인\n", "apply plugin: 'java'\n", "// \n", "apply plugin: 'com.github.johnrengelman.shadow'\n", "\n", "// gradle 스크립트에서 외부 라이브러리를 참\n", "buildscript {\n", " // JCenter라는 저장소. Maven과 Gradle 등 각종 빌드 도구에서 사용할 수 있는 공개 저장소\n", " repositories {\n", " jcenter()\n", " }\n", " // 의존 라이브러리. fat-jar를 만들기 위해 shadowJar라는 라이브러리 사용.\n", " dependencies {\n", " classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'\n", " }\n", "}\n", "\n", "// 저장소 설정\n", "repositories {\n", " // Apache Maven 중앙 저장소를 이용하기 위한 것\n", " mavenCentral()\n", "}\n", "\n", "// 의존 라이브러리. \n", "dependencies {\n", " // 컴파일시 의존 라이브러리. JNA 라이브러리 4.1을 추가로 사용해야 함.\n", " compile 'net.java.dev.jna:jna:4.1.0'\n", " compile 'net.java.dev.jna:jna-platform:4.1.0'\n", "}\n", "\n", "// jar task가 실행될 때 마다 shadowJar가 실행되게 하려면, 아래처럼 jar에 finalizedBy를 달아주면 된다.\n", "jar {\n", " finalizedBy shadowJar\n", " // jar 파일을 만드려면 manifest 파일 정보가 필요함.\n", " // main class는 hello 패키지에 Foo 클래스임.\n", " manifest {\n", " attributes 'Main-Class': 'hello.Foo',\n", " 'Implementation-Title': 'Foo jna Project',\n", " 'Implementation-Version': '1.0'\n", " }\n", "}" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "Writing build.gradle\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "sl8H0z51U-jN" }, "source": [ "* gradle script 참고주소 \n", " - https://araikuma.tistory.com/463\n", " - https://notpeelbean.tistory.com/entry/gradle-buildscript-dependencies-%EC%99%80-dependencies-%EC%9D%98-%EC%B0%A8%EC%9D%B4\n", " - https://blog.leocat.kr/notes/2017/10/11/gradle-shadowjar-make-fat-jar" ] }, { "cell_type": "markdown", "metadata": { "id": "Uy1ZGsSdwy31" }, "source": [ "자바 소스는 src/main/java/hello/Foo.java 로 작성하였습니다." ] }, { "cell_type": "code", "metadata": { "id": "a087ueGxx_q9" }, "source": [ "!mkdir -p src/main/java/hello" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "TLeQy3zdyJxj", "outputId": "21ab64fe-c7d3-40f4-e25e-4229ccdabfc1" }, "source": [ "%%writefile src/main/java/hello/Foo.java\n", "package hello;\n", "\n", "import com.sun.jna.Native;\n", "import com.sun.jna.Platform;\n", "import com.sun.jna.Library;\n", "import com.sun.jna.Pointer;\n", "\n", "public class Foo {\n", " public interface FooLib extends Library {\n", " Pointer Foo_new(int n);\n", " void Foo_bar(Pointer foo);\n", " int Foo_foobar(Pointer foo, int n);\n", " }\n", "\n", " private String sopath;\n", " private FooLib INSTANCE;\n", " private Pointer self;\n", "\n", " private void loadLibrary(int n) {\n", " INSTANCE = (FooLib)Native.loadLibrary(\n", " sopath, FooLib.class\n", " );\n", " self = INSTANCE.Foo_new(n);\n", " }\n", "\n", " public Foo(int n) {\n", " sopath = \"libfoo.so\";\n", " loadLibrary(n);\n", " }\n", " public Foo(String sopath, int n) {\n", " this.sopath = sopath;\n", " loadLibrary(n);\n", " }\n", "\n", " public void bar() {\n", " INSTANCE.Foo_bar(self);\n", " }\n", "\n", " public int foobar(int n) {\n", " return INSTANCE.Foo_foobar(self, n);\n", " }\n", "\n", " public static void main(String[] args) {\n", " String path = System.getProperty(\"user.dir\") + \"/libfoo.so\";\n", " //String path = \"/content/libfoo.so\";\n", " System.out.println(path);\n", " Foo f = new Foo(path,5);\n", "\n", " f.bar();\n", "\n", " System.out.println(\"f.foobar(7) = \" + f.foobar(7));\n", "\n", " int x = f.foobar(2);\n", " System.out.println(\"x = \" + x);\n", " }\n", "}" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "Writing src/main/java/hello/Foo.java\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "meFAcoWNxLa_" }, "source": [ "gradle로 Java 소스를 build 합니다." ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "iY7vvj3wyZyi", "outputId": "a5520a77-0119-49a0-b742-dd808beec59d" }, "source": [ "!gradle build" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "\u001b[mStarting a Gradle Daemon (subsequent builds will be faster)\n", "\u001b[1m> Starting Daemon\u001b[22m\u001b[17D\u001b[1m> Starting Daemon > Connecting to Daemon\u001b[22m\u001b[40D\u001b[0K\u001b[1m> Loading\u001b[22m\u001b[9D\u001b[1m> Loading > settings\u001b[22m\u001b[20D\u001b[1m> Loading\u001b[22m\u001b[0K\u001b[9D\u001b[1m> Configuring\u001b[22m\u001b[13D\u001b[1m> Configuring > 0/1 projects\u001b[22m\u001b[28D\u001b[1m> Configuring > 0/1 projects > root project\u001b[22m\u001b[43D\u001b[1m> Configuring > 0/1 projects > root project > Compiling /content/build.gradle into local build cache > Compiling build file '/content/build.gradle' to cross build script cache\u001b[22m\u001b[175D\u001b[1m> Configuring > 0/1 projects > root project > Compiling /content/build.gradle into local build cache\u001b[22m\u001b[0K\u001b[100D\u001b[1m> Configuring > 0/1 projects > root project\u001b[22m\u001b[0K\u001b[43D\u001b[1m> Configuring > 0/1 projects > root project > Resolving dependencies ':classpath'\u001b[22m\u001b[81DDownload https://jcenter.bintray.com/com/github/jengelman/gradle/plugins/shadow/2.0.1/shadow-2.0.1.pom\n", "\u001b[1m> Configuring > 0/1 projects > root project > Resolving dependencies ':classpath'\u001b[22m\u001b[81D\u001b[1A\u001b[102C\n", "Download https://jcenter.bintray.com/org/codehaus/groovy/groovy-backports-compat23/2.4.4/groovy-backports-compat23-2.4.4.pom\n", "\u001b[1m> Configuring > 0/1 projects > root project > Resolving dependencies ':classpath'\u001b[22m\u001b[81D\u001b[1A\u001b[124C\n", "\u001b[1m> Configuring > 0/1 projects > root project\u001b[22m\u001b[0K\u001b[43DDownload https://jcenter.bintray.com/com/github/jengelman/gradle/plugins/shadow/2.0.1/shadow-2.0.1.jar\n", "\u001b[1m> Configuring > 0/1 projects > root project\u001b[22m\u001b[43D\u001b[1m> Configuring > 0/1 projects > root project > 19 KB/3.09 MB downloaded\u001b[22m\u001b[70D\u001b[1m> Configuring > 0/1 projects > root project > 45 KB/3.09 MB downloaded\u001b[22m\u001b[70D\u001b[1m> Configuring > 0/1 projects > root project > 62 KB/3.09 MB downloaded\u001b[22m\u001b[70D\u001b[1m> Configuring > 0/1 projects > root project > 109 KB/3.09 MB downloaded\u001b[22m\u001b[71D\u001b[1m> Configuring > 0/1 projects > root project > 156 KB/3.09 MB downloaded\u001b[22m\u001b[71D\u001b[1m> Configuring > 0/1 projects > root project > 292 KB/3.09 MB downloaded\u001b[22m\u001b[71D\u001b[1m> Configuring > 0/1 projects > root project > 551 KB/3.09 MB downloaded\u001b[22m\u001b[71D\u001b[1m> Configuring > 0/1 projects > root project > 825 KB/3.09 MB downloaded\u001b[22m\u001b[71D\u001b[1m> Configuring > 0/1 projects > root project > 1.30 MB/3.09 MB downloaded\u001b[22m\u001b[72D\u001b[1m> Configuring > 0/1 projects > root project > 2.16 MB/3.09 MB downloaded\u001b[22m\u001b[72D\u001b[1A\u001b[102C\n", "\u001b[1m> Configuring > 0/1 projects > root project\u001b[22m\u001b[0K\u001b[43DDownload https://jcenter.bintray.com/org/codehaus/groovy/groovy-backports-compat23/2.4.4/groovy-backports-compat23-2.4.4.jar\n", "\u001b[1m> Configuring > 0/1 projects > root project\u001b[22m\u001b[43D\u001b[1A\u001b[124C\n", "\u001b[1m> Configuring > 0/1 projects > root project > Compiling /content/build.gradle into local build cache > Compiling build file '/content/build.gradle' to cross build script cache\u001b[22m\u001b[175D\u001b[1m> Configuring > 0/1 projects > root project\u001b[22m\u001b[0K\u001b[43D\u001b[1m> Configuring > 0/1 projects\u001b[22m\u001b[0K\u001b[28D\u001b[1m> Configuring > 1/1 projects\u001b[22m\u001b[28D\u001b[1m> Configuring\u001b[22m\u001b[0K\u001b[13D\u001b[1m> Building 0% > :compileJava\u001b[22m\u001b[28D\u001b[1m> Building 0% > :compileJava > Resolving dependencies ':compileClasspath'\u001b[22m\u001b[73D:compileJava\u001b[0K\n", "Download https://repo1.maven.org/maven2/net/java/dev/jna/jna/4.1.0/jna-4.1.0.pom\n", "Download https://repo1.maven.org/maven2/net/java/dev/jna/jna-platform/4.1.0/jna-platform-4.1.0.pom\n", "Download https://repo1.maven.org/maven2/net/java/dev/jna/jna/4.1.0/jna-4.1.0.jar\n", "\u001b[1m> Building 0% > :compileJava > 162 KB/893 KB downloaded\u001b[22m\u001b[55D\u001b[1A\u001b[80C\n", "Download https://repo1.maven.org/maven2/net/java/dev/jna/jna-platform/4.1.0/jna-platform-4.1.0.jar\n", "\u001b[1m> Building 0% > :compileJava > 560 KB/1.40 MB downloaded\u001b[22m\u001b[56D\u001b[1A\u001b[98C\n", "\u001b[1m> Building 0% > :compileJava\u001b[22m\u001b[0K\u001b[28D\u001b[1m> Building 0%\u001b[22m\u001b[0K\u001b[13D:processResources \u001b[33mNO-SOURCE\u001b[39m\n", ":classes\n", ":jar\n", "\u001b[1m> Building 33% > :shadowJar\u001b[22m\u001b[27D:shadowJar\u001b[0K\n", "\u001b[1m> Building 33%\u001b[22m\u001b[0K\u001b[14D:assemble\u001b[0K\n", ":compileTestJava \u001b[33mNO-SOURCE\u001b[39m\n", ":processTestResources \u001b[33mNO-SOURCE\u001b[39m\n", ":testClasses \u001b[33mUP-TO-DATE\u001b[39m\n", ":test \u001b[33mNO-SOURCE\u001b[39m\n", ":check \u001b[33mUP-TO-DATE\u001b[39m\n", ":build\n", "\n", "BUILD SUCCESSFUL\n", "\n", "Total time: 11.328 secs\n", "\u001b[0K\u001b[m" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "zitbIOTe1DUg" }, "source": [ "빌드를 하면 build/libs 경로에 2개 파일이 생성됩니다.\n", "\n", "* content.jar: 원래 내 프로젝트\n", "* content-all.jar: JNA 라이브러리가 포함된 Fat-JAR 프로젝트" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "7IkQmnvzzsaE", "outputId": "a04589de-ba3a-45fa-b713-1e35f129df17" }, "source": [ "!ls -lrt build/libs/*.jar" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "-rw-r--r-- 1 root root 1878 May 20 09:05 build/libs/content.jar\n", "-rw-r--r-- 1 root root 1606286 May 20 09:05 build/libs/content-all.jar\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "-aShctuAxBLX" }, "source": [ "다음은 실행 결과입니다." ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "W_5Ck9NaybYa", "outputId": "939d213f-600a-47f8-b94c-a4a6c88a6759" }, "source": [ "!java -jar build/libs/content-all.jar" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "/content/libfoo.so\n", "Value is 5\n", "f.foobar(7) = 12\n", "x = 7\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "qvd8GBHT1rxx" }, "source": [ "다음처럼 Makefile을 생성합니다.\n", "\n" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "NF1Sd-VK1xgG", "outputId": "6e21b724-1003-45d0-93dc-9ddfd0b699d6" }, "source": [ "%%writefile Makefile\n", "SRCS = foo.cpp\n", "OBJS = foo.o\n", "\n", "CFLAGS = $(CFLAG) -D_REENTRANT -D_THREAD_SAFE -D$(_OSTYPE_)\n", "CPPFLAGS= $(CPPFLAG) -D_REENTRANT -D_THREAD_SAFE -D$(_OSTYPE_)\n", "\n", "all : libfoo.so\n", "\n", "libfoo.so :\n", "\tg++ -fPIC -c $(SRCS)\n", "\tg++ -shared -Wl,-soname,$@ -o $@ $(OBJS)\n", "\tgradle build\n", "\n", "clean:\n", "\trm -f *.o core *.out .*list *.ln *.so\n", "\tgradle clean" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "Writing Makefile\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "kaok62361xz-" }, "source": [ "C++, Java 소스를 make로 한꺼번에 build 할 수 있습니다.\n", "\n" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "7mqYGR0P10IK", "outputId": "a02a0b23-7b98-41d4-a8b1-90904de2880d" }, "source": [ "!make clean && make" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "rm -f *.o core *.out .*list *.ln *.so\n", "gradle clean\n", "\u001b[m\u001b[1m> Connecting to Daemon\u001b[22m\u001b[22D\u001b[1m> Loading\u001b[22m\u001b[0K\u001b[9D\u001b[1m> Configuring > 1/1 projects\u001b[22m\u001b[28D:clean\u001b[0K\n", "\n", "BUILD SUCCESSFUL\n", "\n", "Total time: 1.179 secs\n", "\u001b[0K\u001b[mg++ -fPIC -c foo.cpp\n", "g++ -shared -Wl,-soname,libfoo.so -o libfoo.so foo.o\n", "gradle build\n", "\u001b[m\u001b[1m> Connecting to Daemon\u001b[22m\u001b[22D\u001b[0K\u001b[1m> Building 0% > :compileJava\u001b[22m\u001b[28D:compileJava\u001b[0K\n", ":processResources \u001b[33mNO-SOURCE\u001b[39m\n", ":classes\n", ":jar\n", "\u001b[1m> Building 33% > :shadowJar\u001b[22m\u001b[0K\u001b[27D:shadowJar\u001b[0K\n", "\u001b[1m> Building 33%\u001b[22m\u001b[0K\u001b[14D:assemble\u001b[0K\n", ":compileTestJava \u001b[33mNO-SOURCE\u001b[39m\n", ":processTestResources \u001b[33mNO-SOURCE\u001b[39m\n", ":testClasses \u001b[33mUP-TO-DATE\u001b[39m\n", ":test \u001b[33mNO-SOURCE\u001b[39m\n", ":check \u001b[33mUP-TO-DATE\u001b[39m\n", ":build\n", "\n", "BUILD SUCCESSFUL\n", "\n", "Total time: 1.708 secs\n", "\u001b[0K\u001b[m" ], "name": "stdout" } ] }, { "cell_type": "code", "metadata": { "id": "7bq_TMcP2Xqp", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "fcac8cbd-d1fd-4656-8629-03361dea1f1d" }, "source": [ "!java -jar build/libs/content-all.jar" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "/content/libfoo.so\n", "Value is 5\n", "f.foobar(7) = 12\n", "x = 7\n" ], "name": "stdout" } ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "1tqjhV7lzqXl", "outputId": "406fdd26-a4d0-48fc-c131-0500492b699f" }, "source": [ "!ls -lrt /content" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "total 52\n", "drwxr-xr-x 1 root root 4096 May 6 13:44 sample_data\n", "-rw-r--r-- 1 root root 586 May 19 08:28 foo.cpp\n", "-rw-r--r-- 1 root root 4424 May 19 08:28 foo.o\n", "-rwxr-xr-x 1 root root 13320 May 19 08:28 libfoo.so\n", "-rw-r--r-- 1 root root 580 May 19 08:28 foo.py\n", "drwxr-xr-x 2 root root 4096 May 19 08:29 __pycache__\n", "-rw-r--r-- 1 root root 1375 May 19 08:33 build.gradle\n", "drwxr-xr-x 3 root root 4096 May 19 08:33 src\n", "drwxr-xr-x 5 root root 4096 May 19 08:33 build\n" ], "name": "stdout" } ] } ] }