이전 글에서 Java 코드에서 JNA(Java Native Access)를 활용해 C# dll 코드를 호출하는 방법을 정리했습니다. 오늘은 Java 코드에서 호출한 C# dll 함수에서 여러 데이터들이 복합적으로 구성된 DTO(Data Transfer Object)를 자신을 호출한 Java 코드로 반환하는 방법에 대해 간단히 정리해 봅니다. 이것 저것 설명할려다 그냥 코드를 나열하는 것만으로도 훌륭한 설명이 될 것 같습니다.
먼저 C# 코드에서 DTO 클래스를 정의힙니다. 클래스에 StructLayout 애트리뷰트 값을 Sequential로 설정하면 클래스 멤버들이 선언된 순서가 실제 메모리 레이아웃 순서가 됩니다. Java 코드에서 DTO를 정의할 때도 같은 순서로 DTO 선언을 유지해야 합니다.
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public class Status
{
public int Antenna { set; get; }
public string StartFrequency { set; get; }
public string CenterFrequency { set; get; }
public string EndFrequency { set; get; }
}
해당 상태 값을 획득하여 반환하는 함수입니다. 최종적으로 DLL에서 Export 되는 합수입니다.
[DllExport]
public static Status getStatus()
{
Status status = new Status()
{
Antenna = probe.AntennaPort,
StartFrequency = probe.StartFrequency,
CenterFrequency = probe.CenterFrequency,
EndFrequency = probe.StopFrequency,
};
return status;
}
Java에서 DTO를 정의합니다. C# 코드에서 선언한 필드 순서를 @FieldOrder 어노테이션을 통해 DTO 클래스에 정의해 주면 정의된 C# 코드와 호환 가능한 DTO가 정의됩니다.
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
@ToString
@FieldOrder({"antenna", "startFrequency", "centerFrequency", "endFrequency"})
public class Status extends Structure {
public int antenna;
public String startFrequency;
public String centerFrequency;
public String endFrequency;
}
이제 DLL을 로드하고, 연결된 DLL 함수를 호출하면 DLL이 전달하는 상태 DTO를 얻을 수 있습니다.
public interface NativeLibrary extends Library {
Status getStatus();
}
@Component
public class DllBridge {
private NativeLibrary library;
@PostConstruct
private void loadTargetDll() {
library = Native.load("/Test.dll",
NativeLibrary.class);
}
public Status getStatus() {
return library.getStatus();
}
}