2012-04-11 3 views
0

Каков подходящий атрибут signature/marshall для получения выходных параметров с помощью указателей params? До сих пор я попытался это:DllImport Как получить одиночные значения по ссылке

// Function to calculate the norm of vector. !0 on error. 
// int err_NormVec(int size, double * vector, double * norm) 
[DllImport("vectors.dll")] 
int err_NormVec(int size, double[] vector, ref double norm) 

предыдущий подход не выскакивает обратно значение для .NET от C. Я также попытался использовать возлагали GCHandle, с подписью IntPtr.

[DllImport("vectors.dll")] 
int err_NormVec(int size, double[] vector, IntPtr norm) 

public void doSomething() 
{ 
    double norm = 0; 
    // ... 
    GCHandle handle = GCHandle.Alloc(norm, GCHandleType.Pinned); 
    int status = err_NormVec(vector.Lenght, vector, handle.AddrOfPinnedObject()); 
    // ... clean gchandle, check status and so on 
} 

В этом случае я получил значение обратно, но на GCHandle.Target, а не на исходной норме. Это раздражает. Я хотел бы иметь возможность привязать intptr нормы к себе, а не только к копии.

Что такое подходящая подпись для возврата значения с помощью указателя? Есть ли поддерживаемый способ получить IntPtr для значения int?

+0

Я забыл упомянуть, что использую win64. Который раскрыл некоторые плохие практики, которые используют, чтобы успешно работать в win32-приложениях. – fprades

+0

Покажите нам реализацию (или, по крайней мере, подпись) 'err_NormVec'. Вам не нужно указывать двойной, чтобы использовать его как параметр out, 'ref' будет достаточным. –

+0

@EdS: Ты слепой? – leppie

ответ

1

Это работает для меня (как это должно быть):

//C++ DLL (__stdcall calling convention) 
extern "C" __declspec(dllexport) void Foo(double *result) { 
    *result = 1.2; 
} 

//C#  
class Program 
{ 
    [DllImport("Snadbox.dll", CallingConvention=CallingConvention.StdCall)] 
    static extern void Foo(ref double output); 

    static void Main(string[] args) 
    { 
     double d = 0;   
     Foo(ref d); 

     Console.WriteLine(d); // prints "1.2"   
    } 
} 

Передача double используя ключевое слово ref достаточно. Итак, я убежден, что в реализации есть что-то неправильное (или неправильно понятое). Можете ли вы опубликовать эту заявку для нас?

Кроме того, возможно, вы строите версию C++ с использованием соглашения об использовании по умолчанию (cdecl), но .NET использует StdCall. Вы уверены, что они выстроились в очередь? Вы можете упасть, если они смешаны, но нет никакой гарантии. Например, в моем примере, если я изменил сторону C++ на cdecl, тогда параметр out будет считан как 0.

+0

Реализация несущественна, это просто пример, так как на самом деле это сложная библиотека. Если вы хотите, чтобы реализация выполнялась так: int err_NormVec (int size, double [] vector, double * norm) (* norm = 0; for (int i = 0; i fprades

+0

@ fprades.bbva: Ну, и я не хочу звучать грубо, но ваше мнение мало веса, я знаю, почему это не работает. Я показал вам, что упрощенный пример действительно работает, поэтому что-то еще не так, и вы не дали нам достаточной информации, чтобы знать, что это такое. Кроме того, фрагмент, который вы мне дали, ошибочен, поскольку вы добавляете к самому указателю, не разыгрывая его. –

+0

Это то, что можно было бы ожидать и от работы. Однако по какой-то причине это не делает трюк во время выполнения x64. Странный. Возможно, я пропустил что-то со всей пробной и пробной ошибкой. – fprades

Смежные вопросы