You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android下SWIG实现C转Java编译失败:类型不兼容错误求助

编译SWIG生成库时遇到类型不兼容错误

我正在使用一款自研命令协议的C库,每个命令都包含tx和rx结构体类型,还有收发时用于构建/重构数据包的读写器。由于原代码是专有内容,我制作了一个示例项目复现问题。

编译SWIG生成的库时,出现以下错误:

error: incompatible types: int cannot be converted to SWIGTYPE_p_int32_t
    swigtest_native_swigJNI.process(foo.getCPtr(baz), baz, SWIGTYPE_p_void.getCPtr(data), SWIGTYPE_p_int32_t.getCPtr(sz));
                                                                                                                     ^

error: incompatible types: byte cannot be converted to SWIGTYPE_p_uint8_t
    swigtest_native_swigJNI.foo_bar_set(swigCPtr, this, SWIGTYPE_p_uint8_t.getCPtr(value));
                                                                                   ^

我尝试过使用不同的类型映射,并在接口文件中指定函数,但均未奏效。以下是当前最接近编译成功的代码版本,示例项目基于Android Native C++模板创建,修改/添加的代码如下:


CMakeLists.txt

cmake_minimum_required(VERSION 3.22.1)

project("swigtest")

set(CMAKE_C_STANDARD 99)

find_package(SWIG REQUIRED) # Locate SWIG installation
include(UseSWIG) # Add SWIG to CMake

set(SWIG_INTERFACE interface.i) # Path to SWIG interface file
set(CMAKE_SWIG_FLAGS -package com.micro_leads.swigtest.test) # Custom package name parameter

set_property(SOURCE interface.i PROPERTY SWIG_MODULE_NAME swigtest_native_swig) # Set module name

include_directories(${JAVA_INCLUDE_PATH})
include_directories(
        .
)

file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/.swig ${CMAKE_SOURCE_DIR}/../java/com/micro_leads/swigtest/test)
file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/../java/com/micro_leads/swigtest/test)

# Add native source files
set(SOURCES
        native-lib.h
        native-lib.c
)

add_library(${CMAKE_PROJECT_NAME} SHARED
        # List C/C++ source files with relative paths to this CMakeLists.txt.
        ${SOURCES}
)

# Add SWIG library
swig_add_library(
        "${CMAKE_PROJECT_NAME}_native_swig" # name
        LANGUAGE java # language
        SOURCES ${SWIG_INTERFACE} # interface file
        OUTFILE_DIR ${CMAKE_SOURCE_DIR}/.swig # output wrapper file path
        OUTPUT_DIR ${CMAKE_SOURCE_DIR}/../java/com/micro_leads/swigtest/test # output Java files path
)

set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)

# Link swig lib with native lib
target_link_libraries("${CMAKE_PROJECT_NAME}_native_swig" ${JNI_LIBRARIES} ${CMAKE_PROJECT_NAME})

target_link_libraries(${CMAKE_PROJECT_NAME}
        # List libraries link to the target library
        android
        log
        ${JNI_LIBRARIES}
)

native-lib.h

#include <stdint.h>

extern "C" {
typedef struct _foo {
    uint8_t bar;
} foo;

void process(foo *baz, const void *data, int32_t sz);
};

native-lib.c

#include <string.h>

extern "C" {

void process(foo *baz, const void *data, int32_t sz) {
    if (sizeof(foo) < sz) { return; }

    memcpy(baz, data, sz);
}
};

interface.i

%module swigtest_native_swig

%{
#include "native-lib.h"
%}

%include "./typemaps.i"

%include "native-lib.h"

typemaps.i

%typemap(jtype) foo "foo"
%typemap(jstype) foo "foo"
%typemap(jni) foo "jobject"
%typemap(in) foo {
    jsclass cls = (*jenv)->FindClass(jenv, "foo");
    jmethodID constructor = (*jenv)->GetMethodID(jenv, cls, "<init>", "(B)V");
    jfieldID bar_field = (*jenv)->GetFieldID(jenv, cls, "bar", "B");
    jobject obj = (*jenv)->NewObject(jenv, cls, constructor, $1.bar);
    $result = obj;
}
%typemap(out) foo {
    jclass cls = (*jenv)->FindClass(jenv, "foo");
    jfieldID bar_field = (*jenv)->GetFieldID(jenv, cls, "bar", "B");

    $result.bar = (*jenv)->GetByteField(jenv, $input, bar_field);
}

%typemap(jtype) uint8_t "byte"
%typemap(jstype) uint8_t "byte"
%typemap(jni) uint8_t "jbyte"
%typemap(javaout) uint8_t {
    return ($jnicall);
}
%typemap(in) uint8_t {
    $1 = (uint8_t)$input;
}
%typemap(out) uint8_t {
    $result = (jbyte)$1;
}

%typemap(jtype) (const void *, int32_t) "kotlin.ByteArray"
%typemap(jstype) (const void *, int32_t) "kotlin.ByteArray"
%typemap(jni) (const void *, int32_t) "jbyteArray"
%typemap(javaout) (const void *, int32_t) {
    return ($jnicall);
}
%typemap(in) (const void *data, int32_t size) {
    if ($input == null || $input.length != size) {
        throw new IllegalArgumentException("Expected a byte array of length " + size);
    }
    memcpy($1, $input, size);
}
%typemap(out) (const void *, int32_t) {
    jbyteArray result = (*jenv)->NewByteArray(jenv, size);
    if (result != NULL && $1 != NULL) {
        (*jenv)->SetByteArrayRegion(jenv, result, 0, size, (const jbyte *)$1);
    }
    $result = result;
}

MainActivity.kt

package com.micro_leads.swigtest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import com.micro_leads.swigtest.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

//        val foo = test.foo()
//        test.swigtest_native_swig.process(foo, 1, 1)
    }

    companion object {
        // Used to load the 'swigtest' library on application startup.
        init {
            System.loadLibrary("swigtest")
            System.loadLibrary("swigtest_native_swig")
        }
    }
}

内容的提问来源于stack exchange,提问作者Istafein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 03:22:04