2013-03-13 3 views
4

У меня есть функция, которая вызывается из библиотеки в C++, которая была импортирована в проект C#Какой тип C# означает C++ float *?

Я думаю, что он запрашивает указатель на массив. Но я не уверен, как заставить его работать.

вот что он просит function(float*, float*);

, но если я что-то вроде

float[] f = {}; 
float[] f1 = {}; 

function(f,f1); 

он говорит, что есть недопустимые аргументы.

+5

Я смущен - почему вы использовали тег [tag: C#]? Вы имели в виду использовать [tag: C++]? – Oded

+0

Возможный дубликат http://stackoverflow.com/questions/2546706/pointers-in-c-sharp-to-make-int-array –

+1

Это C++-библиотека, импортированная в C# – user1395152

ответ

2

float * - тип указателя поплавка в C#.

Если функция ожидает аргументы указателя плавания (float *), то предполагается, что функция должна работать над указателями, возможно, с использованием арифметики указателя. Поэтому важно сохранить эту подпись.

Чтобы передать массивы с плавающей точкой в ​​C# в качестве указателей с плавающей точкой (float *), вам необходимо вывести/исправить массивы в памяти в небезопасном контексте, чтобы получить указатель на них, который вы можете передать функции, чтобы сохранить ее функциональность:

unsafe 
{ 
    fixed (float* ptr_f = f) //or equivalently "... = &f[0]" address of f[0] 
    fixed (float* ptr_f2 = f2) //or equivalently "... = &f2[0]" address of f2[0] 
    { 
     function(ptr_f, ptr_f2); 
    } 
} 

также необходимо отметить сборку как небезопасные (в свойствах проекта> вкладка построения> позволяют небезопасный код флажок).

+0

, чтобы быть ясным ... сохранение подписи требует наименьших изменений кода, но если вы хотите избежать небезопасного контекста и неэффективного запоминания памяти, просто преобразуйте параметры float pointer (float *) в безопасный массив float (float [ ]) и проверьте логику функции, чтобы убедиться, что нет арифметики указателя, такой как f ++ или f + = 4 или разыменования типа (* (f + 4)). Если указатели с плавающей точкой получают доступ к индексу массива, например f [i], то синтаксис идентичен в C# для доступа к массиву, и это просто стилистическая разница, см. Http://stackoverflow.com/q/1790704/88409 – Triynko

0

, что не работает вообще в C#, при импорте C/C++ библиотеки в C# вы должны использовать IntPtr вместо поплавка *, смотрите здесь несколько примеров: float* from C to C#

0

Он просит указатель поплавка (Адрес машины точки в памяти, которая содержит значение плавающей точки IEEE.) C# не разрешает управляемое использование указателей, поэтому вам нужно будет построить переменную IntPtr и передать ее функции C++.

ПРИМЕЧАНИЕ. Только потому, что он называется IntPtr, это не значит, что это только указатель на целые числа. Int - это потому, что все указатели являются целыми числами. Это может быть указатель на что угодно.

+2

C# не позволяет управлять используемыми указателями? Вы можете использовать их в управляемом (небезопасном) коде, и вы даже можете передать их неуправляемым функциям DllImported ... –

2

Если это метод, импортированный через DLLImport(), вы можете просто заменить указатели массива на типизированный массив.

Так подпись:

[DLLImport("some.dll")] 
SomeMethod(int* a, float* b) 

Становится

[DLLImport("some.dll")] 
SomeMethod(int[] a, float[] b) 

Пожалуйста, обратите внимание, что это предполагает, что с с методом оригинал/++ ожидал массив. Это не будет работать, если указатели не предназначены для ссылки на массивы.

+0

Upvote. Я тоже ответил, полагая, что OP импортировал исходный код в проект C# (было не очень понятно), но если это вызов p-invoke ... это работает для простых типов. CLR автоматически свяжет ссылки на управляемые массивы на время вызова функции (хотя остерегайтесь функций, которые пытаются кэшировать управляемые указатели): http://stackoverflow.com/a/2218540/88409. – Triynko

+0

Необходимо уделять больше внимания сортировке сложных типов, таких как строки, структуры и многомерные массивы, например, требуется ли копирование и/или из неуправляемой памяти и требуется ли какое-либо преобразование (например, из строк Unicode в ANSI) , Это зависит от того, является ли тип «blittable», и указываете ли вы атрибуты таких параметров, как MarshalAs, In или Out (или подразумеваете атрибуты In или Out, используя ключевые слова «out» или «ref»). См. Http://msdn.microsoft.com/en-us/library/23acw07k.aspx и http://msdn.microsoft.com/en-us/magazine/cc164193.aspx. – Triynko

1

Вы должны точно знать , что ожидаемая функция C++.

В C (и C++) все эти функции сигнатур для всех намерений и целей, точно так же:

void foo(float *x , float *y ) ; 
void foo(float *x , float y[]) ; 
void foo(float x[] , float *y ) ; 
void foo(float x[] , float y[]) ; 

Все они принимают 2 аргумента, каждый из которых содержит указатель на (содержит адрес) переменной типа float.И все эти выражения являются абсолютно идентичными в C/C++:

float x[] ; 
float *y ; 

float r1 = *(x+37) ; // all evaluate to the zero-relative 
float r2 = x[37] ; // 37th element of the array. 
float r3 = *(y+37) ; 
float r4 = y[37] ; 
  • Выражение *x говорит, «Принеси float (4 байта), расположенные по адресу, указанному в x
  • Выражение *(x+n),. где n - целочисленное значение, говорит: «Возьмите адрес, содержащийся в x, и к этому добавьте смещение в байтах, полученное выражением sizeof(float) * n. Извлеките значение float, расположенное по результирующему адресу.
  • Массивное выражение x[n] в точности эквивалентно выражению указателя *(x+n).

И поскольку массивы в C/C++ не имеют связанных метаданных, описывающих их размер, вам нужно точно знать, что ожидает функция.

Обычно один передает указатель (вызов по ссылке) для того, чтобы звонящий разыменовываются точку и установить значение для вас — эквивалент C# 's ref и out ключевые слова:

float x ; 
float y ; 
Foo(ref x , ref y) ; // the callee MAY, but is not REQUIRED to set a value before returning to the caller. 
Bar(out x , out y) ; // the callee MUST set a value before returning to the caller. 

идиома ваша функция используется всегда используется для поиска массива, хотя обычно, один проходит также размер:

void foo(float *array , int array_length) ; 

Хотя это не необычно, если функция ожидает массив быть список не- зе ro, чтобы быть чем-то вроде строки C-style, NUL-terminated. Учитывая сигнатура функции, например:

float compute_mean(float *Xs) ; 

Это не редкость для того, чтобы быть как ожидается, будет вызван следующим образом:

float Xs[] = { 3.0 , 2.5 , 9.8 , 7,5 , 0 , } ; 
float mean = compute_mean(Xs) ; 

и определение быть что-то вроде:

float compute_mean(float *Xs) 
{ 
    float n = 0.0 ; 
    float sum = 0.0 ; 
    float mean ; 
    while (*p) 
    { 
    ++n ; 
    sum += *p++ ; 
    } 
    mean = n > 0 ? sum/n : 0.0 ; 
    return mean ; 
} 

Поэтому вам нужно знать семантику метода, который вы вызываете.

Надеюсь, это поможет.