В настоящее время я работаю над переносом программного обеспечения x86 нашей компании на x64 и столкнулся с проблемой.Наш метод из нашей неуправляемой dll, которая возвращает char*
, аварийно завершает работу с 0xc0000374, когда платформа решения переключается на x64, и я хотел бы знать почему.
Собственный код C ++:
#include "stdafx.h"
#include <windows.h>
#include "windef.h"
#define VERSION "3.3.12"
extern "C"
{
__declspec(dllexport) char* WINAPI GetMyVersion()
{
return (char*)VERSION;
}
}
C # DllImport:
using System;
using System.Runtime.InteropServices;
using System.Security;
namespace InteropTest.Adapter
{
[SuppressUnmanagedCodeSecurity]
public unsafe class MyAdapter
{
private const string DLLName = "VersionNumber";
private const string EntryPointName = "GetMyVersion";
[DllImport(DLLName, EntryPoint = EntryPointName, CharSet = CharSet.Ansi)]
internal static extern IntPtr GetMyVersionPtr();
[DllImport(DLLName, EntryPoint = EntryPointName, CharSet = CharSet.Ansi)]
internal static extern string GetMyVersionString();
}
}
GetMyVersionString()
работает только на платформах x86 и вылетает на платформах x64.Однако я могу получить IntPtr
и использовать класс Marshal
для преобразования его в управляемый string
на x86 и x64, например:
using System.Runtime.InteropServices;
using System.Windows;
using InteropTest.Adapter;
namespace InteropTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
var ptr = MyAdapter.GetMyVersionPtr();
var convertedString = Marshal.PtrToStringAnsi(ptr);
// This crashes in x64 build
var directString = MyAdapter.GetMyVersionString();
VersionTextBlock.Text = convertedString;
}
}
}
Я также попытался указатьMarshalAs
Атрибут для возвращаемого значения явно без успеха.Кажется, что 64-битный char*
используется в качестве 32-битного указателя, если вы явно не используете класс Marshal
.Это просто ошибка в .NET или я сделал что-то не так?С моей точки зрения, преобразование с классом Marshal
должно быть эквивалентно использованию атрибута MarshalAs
.
РЕДАКТИРОВАТЬ:
Вот пример проекта, который я сделал для репликацииошибка: https://github.com/chenhuang444/dotNet40InteropCrash
РЕДАКТИРОВАТЬ 2:
Программа и завершает работу с кодом 0xc0000374 без встроенной отладки и сообщает только, что «InteropTest.exe вызвал точку останова», если у меня включена встроенная отладка, страссировка стека:
ntdll.dll!00007ffc0fdc4cfa() Unknown
ntdll.dll!00007ffc0fdcc806() Unknown
ntdll.dll!00007ffc0fdccad1() Unknown
ntdll.dll!00007ffc0fd69a55() Unknown
ntdll.dll!00007ffc0fd77347() Unknown
mscorlib.ni.dll!00007ffbd566759e() Unknown
[Managed to Native Transition]
> InteropTest.exe!InteropTest.MainWindow.OnLoaded(object sender, System.Windows.RoutedEventArgs e) Line 23 C#
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown
РЕДАКТИРОВАТЬ 3:
Неуправляемый код C ++ - это проект в нашем решении, и настройки x64 / x86 настроены, как и в примере, приведенном выше..