int someFunction(const float ** raws)
가 어떻게 C#을에서 float[][]
인수를 사용하여이 함수를 호출 할 수있는 프로토 타입과 C++ 기능이 있다고 가정 해 봅시다? 안전하지 않은 코드를 사용하지 않았을 가능성이 있습니다.
int someFunction(const float ** raws)
가 어떻게 C#을에서 float[][]
인수를 사용하여이 함수를 호출 할 수있는 프로토 타입과 C++ 기능이 있다고 가정 해 봅시다? 안전하지 않은 코드를 사용하지 않았을 가능성이 있습니다.
내가 아는 한 대부분의 작업을 직접해야합니다. Interop은 최상위 배열을 정렬하는 데 도움이되지만 중첩 된 배열을 모두 고정한 다음 완료되면 고정 해제하는 것이 좋습니다. 이 입력 float
어레이에서 데이터 포인트 각각은, 포인터 배열을 구축
using System;
using System.Runtime.InteropServices;
namespace ManagedClient
{
class Program
{
[DllImport("UnmanagedDll.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int UseFloats([MarshalAs(UnmanagedType.LPArray)] IntPtr[] raws);
static void Main(string[] args)
{
float[][] data =
{
new[] { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f },
new[] { 1.0f, 1.1f, 1.2f, 1.3f },
new[] { 2.0f },
new[] { 3.0f, 3.1f }
};
var handles = new GCHandle[data.Length];
var pointers = new IntPtr[data.Length];
try
{
for (int i = 0; i < data.Length; ++i)
{
var h = GCHandle.Alloc(data[i], GCHandleType.Pinned);
handles[i] = h;
pointers[i] = h.AddrOfPinnedObject();
}
UseFloats(pointers);
}
finally
{
for (int i = 0; i < handles.Length; ++i)
{
if (handles[i].IsAllocated)
{
handles[i].Free();
}
}
}
}
}
}
이 코드는 한 가지 방법을 도시한다. (C 함수가 데이터가 도착하기를 기대하는 형식입니다.) C 코드가 각 하위 배열의 길이를 아는 방법은 당신에게 달려 있습니다. 현실에서
__declspec(dllexport) int __stdcall UseFloats(const float ** raws)
{
printf("%f %f %f %f %f\n", raws[0][0], raws[0][1], raws[0][2], raws[0][3], raws[0][4]);
printf("%f %f %f %f\n", raws[1][0], raws[1][1], raws[1][2], raws[1][3], raws[0][4]);
printf("%f\n", raws[2][0]);
printf("%f %f\n", raws[3][0], raws[3][1]);
return 0;
}
당신은 아마도 서브 어레이의 각이 얼마나 오랫동안 관리되지 않는 코드를 말할 뭔가를하고 싶은거야 : 내 테스트 코드에서 난 그냥 C# 코드는 전달 일치하도록 하드 코딩 - 선택한 관리되지 않는 함수 서명은 호출 된 코드가 각 하위 배열의 길이를 알 수있는 방법을 제공하지 않습니다. (아마도 당신이 ** 플로트를 사용하는 이유는 당신이 들쭉날쭉 배열을 원하기 때문에.이 아닌 경우, 각 부분 배열이 정확히 같은 길이 인 경우, 그것은 배열 대신 여기 직사각형 배열을 사용하는 것이 더 효율적 훨씬 것 포인터를 사용하면 쉽게 마샬링을 할 수 있습니다.)
좋은 답변입니다. 당신은 아마 "아마도 당신은 플로트를 사용하는 이유는 [] []" "** 떠"하지 의미와 그 밑줄 또는 두 개의 차원 배열 ([,], float를) 자동으로 마샬링 할 수있는 경우가 있기 때문에 경우에 굵은 글씨로해야한다. –
감사합니다. 그러나 나는 내가 쓴 것을 의미했다 : 나는 그가 부르려고하는 관리되지 않는 기능의 서명이기 때문에 "float **"이라고 비난했다.그것은 문제의 근본 원인 인 서명입니다. (C#에서 float [,]로 전환하면 관리되지 않는 서명이 계속 float ** 인 경우 많은 도움이되지 않습니다. 관리되지 않는 서명에는 문제의 핵심 인 포인터 배열이 필요합니다. float [,]로 시작하면 하나의 객체 만 고정해야하지만 IntPtr []을 작성해야합니다.) 가능한 한 관리되지 않는 서명을 변경하는 것이 가장 좋은 해결책이라고 생각합니다. –
@Ian 왜 [MarshalAs (UnmanagedType.LPArray)]를 사용합니까? 그리고 당신이 그 속성을 사용하지 않는다면 디폴트 마샬링은 무엇입니까? – hattenn
이안이 이미 귀하의 질문에 대답 했으므로 C++ 측에서 SAFEARRAY를 사용하는 것이 좋습니다.
SAFEARRAY는 C/C++의 모호한 배열 정의 문제에 대한 COM 응답으로, 기본 요소의 수와 크기를 포함하고 .Net 배열에 더 적합한 구조입니다. 이들을 사용하면 C#의 배열을 자동으로 마샬링 할 수 있습니다.
SAFEARRAY는 C++에서 작동하기가 어렵지만 ATL에는 일을 쉽게하기위한 멋진 래퍼가 있습니다. 가능하다면 C++ 함수를 사용하거나 C++에서 작성된 마샬링 코드가있는 .Net을 사용하는 interop 용 C++ 래퍼 작성을 고려하십시오.
불행히도, C++ 코드는 다른 사람이 작성한 것으로,이를 제어 할 권한이 없습니다. 생각을 제안! – hattenn
'float [] []'은 기본적으로'float ** '와 근본적으로 다르므로 아마 그렇지 않을 것입니다. –
글쎄 그건 불가능해서는 안됩니다. 나는 방법이있을 것이라고 확신합니다. 그것이 내가 "마샬링"이라고 부른 이유입니다. – hattenn
나는 그것을하기위한 해킹 방법은 float [] []를 클래스/구조체에 넣고 그 대신에 주위를 전달하는 것이다. 만약 스택에가 함수에 전달할 때마다 전체 플로트 [] []과 중복되지 않도록 –