Приложение .NET вызывает неуправляемую DLL, параметры содержат странные символы

Я создаю приложение .NET для вызова неуправляемой DLL (Юникод).

Ниже приведен заголовок неуправляемой DLL:

#pragma once

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

//  Callback function for ProcessFileAPI. The function is called whenever progress advances.
typedef VOID (CALLBACK* LPPROGRESSPROC)(CONST BYTE btProgress, LPVOID lParam);

#pragma pack(1)

//  Options for ProcessFileAPI
typedef struct _OPTIONS1
{
    BOOL m_bOption1;
    BOOL m_bOption2;
} OPTIONS1, *LPOPTIONS1;

#pragma pack()

DWORD WINAPI ProcessFileAPI(LPCTSTR lpSrcFileName, LPCTSTR lpDstFileName, LPPROGRESSPROC lpProgressProc, LPVOID lpProgProcParam,
                           LPBOOL pbCancel, CONST LPOPTIONS1 lpOptions1);

#ifdef __cplusplus
}
#endif

И .cpp для неуправляемой DLL:

extern "C"  DWORD WINAPI ProcessFileAPI(LPCTSTR lpSrcFileName, LPCTSTR lpDstFileName, LPPROGRESSPROC lpProgressProc, LPVOID lpProgProcParam,
                                       LPBOOL pbCancel, CONST LPOPTIONS1 lpOptions1)
{
    TRACE(_T("SrcFileName: %s. DstFileName: %s."), lpSrcFileName, lpDstFileName);
    return  0;
}

Ниже приведен код .NET для этой функции:

using System;
using System.Runtime.InteropServices;

namespace SDKAPI
{
    public struct TOptions1
    {
        public bool bOption1;
        public bool bOption2;
    }   // end TOptions1

    public delegate void TProgressProc(byte btProgress, IntPtr lParam);
}

namespace SDKAPI.Units
{
    public class SDKAPI
    {
        [DllImport("SDK.DLL")]
        public static extern uint ProcessFileAPI(string lpSrcFileName, string lpDstFileName, TProgressProc pgrsproc, IntPtr lpProgProcParam, ref int pbCancel, ref TOptions1 options);

    } // end SDKAPI
}

А ниже вызов функции:

Options1.bOption1 = true;
Options1.bOption2 = false;

// Process the file
FCancel = 0;

RetCode = SDKAPI.Units.SDKAPI.ProcessFileAPI(txtSrcFile.Text, txtDstFile.Text, new SDKAPI.TProgressProc(this.ProgressProc), IntPtr.Zero, ref FCancel, ref Options1);

При вызове DLL с помощью txtSrcFile.Text = "a" и txtDstFile.Text = "b", но я отлаживаю DLL и обнаруживаю, что параметр lpSrcFileName становится "a", за которым следует множество странных символов. Почему?

Обычно я использую управляемый уровень C++/CLI, но C# string — это не то же самое, что LPCTSTR. В объявлении extern на C# попробуйте добавить [MarshalAs(UnmanagedType.LPWStr)] перед string lpSrcFileName. По умолчанию — BStr, см. здесь

ChrisMM 09.04.2024 13:09

@ChrisMM LPCTSTR тоже не LPWStr.

GSerg 09.04.2024 13:50

@alancc Вы скомпилировали dll как Unicode или нет? Добавьте эту информацию в свой [DllImport], используя свойство CharSet.

GSerg 09.04.2024 13:51

@GSerg, DLL находится в Юникоде.

alancc 09.04.2024 15:52

Затем используйте CharSet.Unicode в объявлении функции. Если он отсутствует, он принимает 8-битные символы, и строка преобразуется в китайский язык.

Hans Passant 09.04.2024 16:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам необходимо выяснить, использует ли неуправляемая DLL Unicode или нет. Если да, то нужно CharSet.Unicode иначе CharSet.Ansi.

Также необходимо установить пак.

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct TOptions1
{
    public bool bOption1;
    public bool bOption2;
}

[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate void TProgressProc(byte btProgress, IntPtr lParam);

[DllImport("SDK.DLL", CharSet = CharSet.Unicode)]
public static extern uint ProcessFileAPI(
    string lpSrcFileName, string lpDstFileName, TProgressProc pgrsproc,
    IntPtr lpProgProcParam, ref bool pbCancel, [In] in TOptions1 options);
BOOL , в отличие от bool, — это I4, а не I1. Для этого есть UnmanagedType.Bool, который в любом случае является значением по умолчанию.
GSerg 09.04.2024 15:31

ОК, исправил это. Меня всегда смущают эти двое.

Charlieface 09.04.2024 15:46

DLL находится в Unicode, я обновил свой вопрос.

alancc 09.04.2024 15:54

Несколько вопросов: 1. Поскольку BOOL отличается от bool, почему в кодах все еще используется bool? 2. «[In] в параметрах TOptions1» вызовет ошибку компилятора, поэтому я заменяю его на «[In] TOptions1 options», но передаваемые значения всегда неверны.

alancc 09.04.2024 16:22
bool в C# есть только один тип. Вопрос был только в том, на что это сопоставить при маршаллинге. Какую ошибку компилятора вы получаете? Отлично работает в .NET 8 dotnetfiddle.net/KMe2Px Если вы используете .NET Framework, измените его обратно на ref. Не используйте его без ref или in, иначе это не сработает.
Charlieface 09.04.2024 16:41

Я использую C# в Visual Studio 2008, и компилятор видит «C:\Windows\Microsoft.NET\Framework\v3.5». Так что я думаю, что это .net framework.

alancc 09.04.2024 16:55

Я предполагаю, что вы понимаете, что поддержка VS 2008 прекратилась в 2018 году, и что в .NET 3.5, хотя она все еще поддерживается, отсутствуют многие исправления и улучшения производительности и удобства использования, поэтому я настоятельно рекомендую вам обновиться как можно скорее. В будущем обязательно отмечайте .net-3.5, потому что люди не поймут.

Charlieface 09.04.2024 17:12

Я понимаю. Я добавил тег .net-3.5. Также могу ли я использовать uint в качестве типа для C++ BOOL? Поскольку uint в C# имеет размер 4 байта, что в точности соответствует C++ BOOL.

alancc 10.04.2024 07:35

Да, ты можешь, если хочешь

Charlieface 10.04.2024 09:53

Другие вопросы по теме