Я звоню в неуправляемую dll. То, как я это делаю, выглядит так:
// Kernel functions used to load dll
#region Kernell 32
[DllImport("kernel32")]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
#endregion
public void Test()
{
IntPtr dllHandle = LoadLibrary(@"C:\Program Files (x86)\SEGGER\JLinkARM_SDK_V484c\JLinkARM.dll");
// here is a function that enables me to read data from a chip
var ptr = GetProcAddress(loadedDllHandle, @"JLINK_HSS_Read");
{
Delegate1 readMem = (Delegate1)Marshal.GetDelegateForFunctionPointer(ptr, typeof(Delegate1));
// then if I want to read an integer from memory address 0x100 I will do
byte[] dataToRead = new byte[4];
unsafe
{
fixed (byte* fixedPointer = dataToRead)
{
// <----- FIRST CALL TO DLL WORKS GREAT!!!!!!!!!!!!!!!!
var retn = readMem(0x100, 4, (IntPtr)fixedPointer);
}
}
}
// there is another function called JLINK_HSS_Start
ptr = GetProcAddress(loadedDllHandle, @"JLINK_HSS_Start");
{
Delegate2 x = (Delegate2)Marshal.GetDelegateForFunctionPointer(ptr, typeof(Delegate1));
unsafe
{
var m = x(5); // here I get an exception!
}
}
}
ИСКЛЮЧЕНИЕ, ЧТО Я ПОЛУЧАЮ:
Дополнительная информация: вызов функции PInvoke "Jlink! Jlink.HighSpeedSampling.Hss + JLINK_HSS_Start_Handler :: Invoke" имеет несбалансированный стек. Вероятно, это связано с тем, что управляемая подпись PInvoke не соответствует неуправляемой целевой сигнатуре. Убедитесь, что соглашение о вызове и параметры сигнатуры PInvoke соответствуют целевой неуправляемой подписи.
Первый вызов функции работает второй
Другими словами, я не могу назвать x (5). Наверное, потому что мне нужно передать больше параметров. Я не знаю подпись этого метода. Как я могу узнать подписи метода. Указатель не равен нулю, поэтому я знаю, что функция существует. Если я неправильно набираю имя метода, я получаю нулевой указатель. Одно из решений заключается в том, чтобы печатать разные сигнатуры до тех пор, пока они не сбой. Могло быть так много комбинаций. Короче говоря, я знаю, что указатель указывает на функцию. Как узнать подпись этой функции?
Вам нужно будет посмотреть в заголовочном файле, который поставляется вместе с SDK. Одна вещь, на которую нужно обратить внимание, - это конвенция о вызове. Вам может потребоваться добавить [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
к замедлению делегата, не делая этого, когда это потребуется, приведет к этой точной ошибке (так же как и неправильные параметры).
Во втором звонке есть опечатка:
Delegate2 x = (Delegate2)Marshal.GetDelegateForFunctionPointer(ptr, typeof(Delegate1));
Вы передаете тип Delegate1 и затем передаете делегату2.