P/Вызов функции с вариативной сигнатурой

У меня есть приложение C#.NET 2.0 CF, которое импортирует функцию из собственной библиотеки DLL со следующей подписью:

__declspec( dllexport ) void DLL_Foo( int count, ... );

Мое приложение C# P/Invokes, которое работает следующим образом:

public sealed class MyObject
{
    public void Foo()
    {
        NativeMethods.DLL_Foo(2, __arglist("a","b")); 
    }

    internal static class NativeMethods
    {
        [DllImport("My.dll")]
        internal static extern void DLL_Foo(int count, __arglist);
    }
}

Но когда я вызываю MyObject.Foo, я получаю System.MissingMethodException.

Что мне нужно изменить, чтобы это заработало?

Спасибо, PaulH


Изменить: если я изменю определение импорта на:

internal static extern void DLL_Foo(int count, [MarshalAs(UnmanagedType.LPWStr)]string a, [MarshalAs(UnmanagedType.LPWStr)]string b);

затем позвоните:

NativeMethods.DLL_Foo(2, "a", "b"); 

Работает без проблем, так что это что-то с моим __arglist использованием.


person PaulH    schedule 15.12.2010    source источник


Ответы (2)


Я не уверен (и я никогда этого не делал), можете ли вы иметь params аргументов в P/Invoke, но вы можете попробовать.

internal static extern void DLL_Foo(int count, params string[] args);
person Aliostad    schedule 15.12.2010
comment
Это очень интересно. Как только я перехожу к методу NativeMethods.DLL_Foo(2, new string[]{"a", "b"}), я не иду дальше. Программа продолжает работать, но не переходит к следующей строке кода. Я также попробовал это против wsprintf() из coredll.dll, чтобы убедиться, что это не непослушная DLL. Тот же результат. - person PaulH; 16.12.2010
comment
Упс. Я должен был смотреть на экран устройства. Произошло собственное исключение в... Код 0x80000002, который, я считаю, является несоответствием типа данных. - person PaulH; 16.12.2010
comment
@Paul Я думаю, вам, вероятно, придется иметь несколько перегрузок с несколькими строками, и это должно помочь, хотя и не приведет к тому, чего вы хотели. - person Aliostad; 16.12.2010
comment
Кажется, он работает в некомпактной среде. bartdesmet.net/blogs/bart/archive/2006/09/ 28/4473.aspx stackoverflow.com/questions/2124490/ - person PaulH; 16.12.2010

Вы должны использовать CallingConvention = CallingConvention.Cdecl для вашего DllImport. В описании CallingConvention.Cdecl это указано.

using LPWORD = System.IntPtr;
using LPVOID = System.IntPtr;

[DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern LPVOID extFunc(LPWORD lpdwMandatory,__arglist);

И затем Вы можете вызвать функцию extFunc:

extFunc(lp1,__arglist( 0xFF,0x6A,0xAA));
person Vasiliy    schedule 31.08.2012