Я пишу проект C++/CLI с помощью COM Interop, чтобы разоблачить методы и объекты для клиента VBA.Почему RegAsm добавляет 'W' к некоторым сигнатурам метода?
Все было хорошо до сих пор, но у меня возникает странная проблема: некоторые методы экспортируются с (нежелательным) суффиксом «W» (например, GetUserNameW
)!
Позвольте мне объяснить подробнее ...
Я утилита класса написал так:
MyUtils.h
#pragma once
namespace MyApp {
[System::Runtime::InteropServices::ComVisible(true)]
[System::Runtime::InteropServices::Guid("...guid...")]
[System::Runtime::InteropServices::InterfaceType(System::Runtime::InteropServices::ComInterfaceType::InterfaceIsDual)]
public interface class IMyUtils
{
System::String^ CombinePaths(System::String^ path1, System::String^ path2);
System::String^ GetDocumentsDirectory();
System::String^ GetMachineName();
System::String^ GetSystemDirectory();
System::String^ GetUserName();
};
[System::Runtime::InteropServices::ComVisible(true)]
[System::Runtime::InteropServices::Guid("...another guid...")]
[System::Runtime::InteropServices::ClassInterface(System::Runtime::InteropServices::ClassInterfaceType::None)]
public ref class MyUtils : IMyUtils
{
public:
MyUtils();
virtual System::String^ CombinePaths(System::String^ path1, System::String^ path2);
virtual System::String^ GetDocumentsDirectory();
virtual System::String^ GetMachineName();
virtual System::String^ GetSystemDirectory();
virtual System::String^ GetUserName();
};
}
MyUtils.cpp
#include "stdafx.h"
#include "MyUtils.h"
using namespace System;
using namespace System::Data;
using namespace System::IO;
using namespace System::Runtime::InteropServices;
namespace MyApp
{
MyUtils::MyUtils()
{
// Do nothing...
}
String^ MyUtils::CombinePaths(String^ path1, String^ path2)
{
return Path::Combine(path1, path2);
}
String^ MyUtils::GetDocumentsDirectory()
{
return Environment::GetFolderPath(Environment::SpecialFolder::MyDocuments);
}
String^ MyUtils::GetMachineName()
{
return Environment::MachineName;
}
String^ MyUtils::GetSystemDirectory()
{
return Environment::SystemDirectory;
}
String^ MyUtils::GetUserName()
{
return Environment::UserName;
}
}
Здесь ничего сложного.
Затем я создаю TLB и зарегистрировать сборку с этой командной строки:
regasm MyLib.dll /codebase /tlb
Теперь, когда я пытаюсь использовать объект на клиенте VBA, у меня есть:
Dim utils As New MWUtils
utils.CombinePaths "C:\Windows", "System32"
utils.GetDocumentsDirectory
utils.GetMachineName
utils.GetSystemDirectoryW '<== What?
utils.GetUserNameW '<== Again?
Обратите внимание на суффикс 'W' на GetSystemDirectory
и GetUserName
методах!
Промежуточный вопрос: откуда он взялся?
Хорошо, посмотрите в сгенерированный IDL для интерфейса:
[
uuid(...guid...),
dual,
oleautomation
]
interface IMyUtils : IDispatch {
[id(0x60020000)]
HRESULT CombinePaths(
[in] BSTR path1,
[in] BSTR path2,
[out, retval] BSTR* pRetVal
);
[id(0x60020001)]
HRESULT GetDocumentsDirectory([out, retval] BSTR* pRetVal);
[id(0x60020002)]
HRESULT GetMachineName([out, retval] BSTR* pRetVal);
[id(0x60020003)]
HRESULT GetSystemDirectoryW([out, retval] BSTR* pRetVal);
[id(0x60020004)]
HRESULT GetUserNameW([out, retval] BSTR* pRetVal);
};
Это теперь ясно, что инструмент Regasm имеет изменять сигнатуры методов, но почему?
Суффикс «W» указывает строку Unicode, но это первый раз, когда я вижу такое изменение!
Заключительный вопрос # 1: Почему RegAsm указывает строки Unicode для этих двух методов?
Заключительный вопрос # 2: Как я могу подавить это «изменение»?
Очень тонкий. Еще одна ловушка C++/CLI, которая не существует с C#. Итак, я добавляю '#undef GetUserName' и' #undef GetSystemDirectory' после включения stdafx.h, но ПЕРЕД включением MyUtils.h и он работает! Большое спасибо! –