在使用jna将c代码Map到java时,应该为这种结构使用哪些类?

vu8f3i0k  于 2021-08-25  发布在  Java
关注(0)|答案(1)|浏览(492)

这是我的第一个问题,我认为这是解决这个问题的最佳社区。
我正在开发一个与图像处理相关的java应用程序,并尝试使用jna使用cviptools库(用c/c++编写)的函数,但这是我第一次使用此方法。
当我试图执行一个小测试来检查我是否能够执行c函数rst_不变量时,我得到了以下错误:

  1. java.lang.reflect.InvocationTargetException
  2. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  3. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  4. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  5. at java.lang.reflect.Method.invoke(Method.java:498)
  6. at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
  7. at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
  8. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  9. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  10. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  11. at java.lang.reflect.Method.invoke(Method.java:498)
  12. at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
  13. Caused by: java.lang.Error: Invalid memory access
  14. at com.sun.jna.Native.invokePointer(Native Method)
  15. at com.sun.jna.Function.invokePointer(Function.java:497)
  16. at com.sun.jna.Function.invoke(Function.java:441)
  17. at com.sun.jna.Function.invoke(Function.java:361)
  18. at com.sun.jna.Library$Handler.invoke(Library.java:265)
  19. at com.sun.proxy.$Proxy2.rst_invariant(Unknown Source)
  20. at aplicacion.Main.main(Main.java:75)
  21. ... 11 more
  22. Exception running application aplicacion.Main

显然,这个错误与内存管理有关,但我没有足够的知识和经验来检测它。我认为问题可能与c数据类型和我使用的java类之间的无效关系有关,但我不确定。
我附上了原始c函数的代码、结构和我尝试过的Map。
每一个改进代码的建议都是受欢迎的。如果您需要其他信息,请告诉我:d
非常感谢你!!!
rst_不变量.c

  1. double* rst_invariant(Image* label_image, int r, int c) {
  2. int** image; /* 2-d matrix data pointer */
  3. int y, /* Índice de fila */
  4. x, /* Índice de columna */
  5. p, q, i, j, label;
  6. double* ptr;
  7. double moment[2][2], /* zeroth moment and first moment */
  8. moment1[4][4], /* central moment */
  9. moment2[4][4]; /* normalization of central moment */
  10. unsigned int rows, /* Número de filas en la imagen */
  11. cols; /* Número de columnas en la imagen */
  12. rows = getNoOfRows_Image(label_image);
  13. cols = getNoOfCols_Image(label_image);
  14. ptr = (double*)malloc(7 * sizeof(double));
  15. printf("hola\n");
  16. for (i = 0; i < 7; i++) ptr[i] = 0.0;
  17. for (i = 0; i < 2; i++)
  18. for (j = 0; j < 2; j++) moment[i][j] = 0.0;
  19. for (i = 0; i < 4; i++)
  20. for (j = 0; j < 4; j++) {
  21. moment1[i][j] = 0.0;
  22. moment2[i][j] = 0.0;
  23. }
  24. /*
  25. Compara el valor del píxel de la ubicación (y,x)
  26. con el valor del umbral. Si es más grande que
  27. el umbral escribe 255 en la localización, si no escribe 0
  28. */
  29. image = (int**)getData_Image(label_image, 0);
  30. label = image[r][c];
  31. for (p = 0; p <= 1; p++) {
  32. for (q = 0; q <= 1; q++) {
  33. for (y = 1; y < rows; y++) {
  34. for (x = 1; x < cols; x++) {
  35. if (image[y][x] == label) {
  36. moment[p][q] = moment[p][q] + pow(x, p) * pow(y, q) * 1; /* Para imágenes binarias, considera patrones binarios. Donde f(x, y) = 1 or 0, aquí 1 es blanco, 0 es negro */
  37. }
  38. }
  39. }
  40. }
  41. }
  42. for (p = 0; p <= 3; p++) {
  43. for (q = 0; q <= 3; q++) {
  44. for (y = 1; y < rows; y++) {
  45. for (x = 1; x < cols; x++) {
  46. if (image[y][x] == label) {
  47. moment1[p][q] = moment1[p][q] + pow((x - (moment[1][0] / moment[0][0])), p) * pow((y - (moment[0][1] / moment[0][0])), q) * 1; /* Para imágenes binarias, considera patrones binarios. Donde f(x, y) = 1 or 0, aquí 1 es blanco, 0 es negro */
  48. }
  49. }
  50. }
  51. }
  52. }
  53. for (p = 0; p < 4; p++) {
  54. for (q = 0; q < 4; q++) {
  55. if ((p + q) == 2 || (p + q) == 3) {
  56. moment2[p][q] = moment1[p][q] / pow(moment1[0][0], ((p + q) * 0.5) + 1);
  57. }
  58. }
  59. }
  60. ptr[0] = moment2[2][0] + moment2[0][2];
  61. ptr[1] = (moment2[2][0] - moment2[0][2]) * (moment2[2][0] - moment2[0][2]) + 4 * (moment2[1][1]) * (moment2[1][1]);
  62. ptr[2] =
  63. (moment2[3][0] - 3 * moment2[1][2]) * (moment2[3][0] - 3 * moment2[1][2]) + (3 * moment2[2][1] - moment2[0][3]) * (3 * moment2[2][1] - moment2[0][3]);
  64. ptr[3] =
  65. (moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) + (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3]);
  66. ptr[4] =
  67. (moment2[3][0] - 3 * moment2[1][2]) * (moment2[3][0] + moment2[1][2]) * ((moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) - 3 * (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3])) + (3 * moment2[2][1] - moment2[0][3]) * (moment2[2][1] + moment2[0][3]) * (3 * (moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) - (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3]));
  68. ptr[5] =
  69. (moment2[2][0] - moment2[0][2]) * ((moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) - (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3])) + 4 * (moment2[1][1]) * (moment2[3][0] + moment2[1][2]) * (moment2[2][1] + moment2[0][3]);
  70. ptr[6] =
  71. (3 * moment2[2][1] - moment2[0][3]) * (moment2[3][0] + moment2[1][2]) * ((moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) - 3 * (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3])) - (moment2[3][0] - 3 * moment2[1][2]) * (moment2[2][1] + moment2[0][3]) * (3 * (moment2[3][0] + moment2[1][2]) * (moment2[3][0] + moment2[1][2]) - (moment2[2][1] + moment2[0][3]) * (moment2[2][1] + moment2[0][3]));
  72. return ptr;
  73. }

图像结构

  1. typedef struct {
  2. int image_format;
  3. int color_space;
  4. int bands;
  5. MATRIX**image_ptr;
  6. } IMAGE;
  7. # define bandP image_ptr
  8. typedef IMAGE Image;

矩阵结构

  1. typedef struct {
  2. int data_type;
  3. int data_format;
  4. unsigned int rows;
  5. unsigned int cols;
  6. char**rptr;
  7. char**iptr;
  8. } MATRIX;
  9. typedef MATRIX Matrix;

java中的图像结构Map

  1. @Structure.FieldOrder({ "data_type", "color_space", "bands", "image_ptr" })
  2. public class Image extends Structure {
  3. public int data_type; // enum se mapea como int
  4. public int color_space; // enum se mapea como int
  5. public int bands;
  6. public Matrix image_ptr; // MATRIX**(doble puntero a struct)
  7. public Image() {
  8. super();
  9. }
  10. public Image(Matrix image_ptr) {
  11. super();
  12. // Valores por defecto, quizás se puedan eliminar
  13. this.data_type = 0;
  14. this.color_space = 0;
  15. this.bands = 0;
  16. this.image_ptr = image_ptr;
  17. }

java中的矩阵结构Map

  1. @FieldOrder({ "data_type", "data_format", "rows", "cols", "rptr", "iptr" })
  2. public class Matrix extends Structure {
  3. public int data_type;
  4. public int data_format;
  5. public int rows;
  6. public int cols;
  7. public Pointer rptr;
  8. public Pointer iptr;
  9. // CONSTRUCTOR
  10. public Matrix() {
  11. super();
  12. }
  13. public Matrix (int imagenMatriz[][], int columnas, int filas) {
  14. super();
  15. // Valores por defecto, quizás se puedan eliminar
  16. this.data_type = 0;
  17. this.data_format = 0;
  18. // Filas y columnas
  19. this.rows = filas;
  20. this.cols = columnas;
  21. // Asignación de memoria para la matriz
  22. this.rptr = new Memory(this.rows * 8); // Creamos vector de Pointer con tamanho = alto de la imagen (número de filas). Cada puntero ocupa 8 bytes.
  23. for(int i = 0; i < this.rows; i++) {
  24. Pointer fila = new Memory(this.cols * Integer.BYTES);
  25. this.rptr.setPointer(i * 8, fila);
  26. for(int j = 0; j < this.cols; j++) {
  27. this.rptr.getPointer(i * 8).setInt(j * Integer.BYTES, imagenMatriz[j][i]); //Comentar y revisar esto, creo que está OK
  28. }
  29. }
  30. // Probablemente, eliminable, de momento lo dejamos así
  31. this.iptr = new Memory(8);
  32. }

java中的接口定义

  1. public interface I_CVIPTools extends Library {
  2. I_CVIPTools INSTANCE = (I_CVIPTools) Native.load("rst_invariant", I_CVIPTools.class);
  3. public Pointer rst_invariant(Image label_image, int r, int c);
  4. }

我试图执行的测试(我在最后一行中得到错误)

  1. Matrix test_matrix = new Matrix(test.getMatriz(), test.getColumnas(), test.getFilas());
  2. System.out.println("Píxel (702, 242) = " + test_matrix.getPixel(702, 242));
  3. Image test_image = new Image(test_matrix);
  4. Pointer vector = new Memory(7 * Double.BYTES);
  5. vector = I_CVIPTools.INSTANCE.rst_invariant(test_image, 242, 702);
i1icjdpr

i1icjdpr1#

Map结构时要理解的关键点是它们何时被值和引用使用。
默认情况下,未装饰的结构是 ByReference 在方法/函数参数中使用时,以及 ByValue 在结构内部使用时。如果需要以默认方式以外的方式使用它,则需要专门使用适当的接口。
这个 Image 结构包含此本机元素:

  1. MATRIX**image_ptr;

在jna中,这只是一个指针,或者 ByReference 结构。您错误地将其Map为内联 ByValue (默认情况下)结构:

  1. public Matrix image_ptr;

这就是导致当前“无效内存访问”错误的原因。你正在填充 Image 使用来自您的 Matrix 结构。但是本机代码处理 Image struct看到两个整数 data_typedata_format 并试图将它们解释为指向结构数据所在位置的指针。你不拥有被指向的记忆。
我看不到全部 Matrix Map在您的问题中,但您需要包括 ByReference 间接寻址级别之一的标记。

  1. @Structure.FieldOrder({ "data_type", "data_format", "rows", "cols", "rptr", "iptr" })
  2. public class Matrix extends Structure {
  3. public static class ByReference implements Structure.ByReference {
  4. }
  5. public int data_type;
  6. public int data_format;
  7. public int rows;
  8. public int cols;
  9. public Pointer rptr;
  10. public Pointer iptr;
  11. }

此外,由于有两种间接方式,您需要实际传递 PointerByReference 给你 Image 结构,因此您将使用以下内容替换当前Map:

  1. public PointerByReference image_ptr;

要填充该值,请执行以下操作:

  1. Matrix.ByReference matrix = new Matrix.ByReference();
  2. test_image.image_ptr = new PointerByReference(matrix.getPointer());
展开查看全部

相关问题