将 BSTR 字符串作为托管代码和非托管代码之间的边界传递(COM 互操作)
passing BSTR string as a perimeter between managed and unmanaged code (COM interop)
在处理 com interop 时,我遵循了有关此 link 的教程。代码运行良好,因为我根据我的要求做了一些修改,但是在处理 string.I 时出现了问题我在这里使用 BSTR 字符串作为周边。
这是我从 c++
调用的 c# 函数
public string ShowDialog([MarshalAs(UnmanagedType.BStr)] string stringToPrint)
{
// Console.WriteLine(" Enter TOTP input:");
// stringToPrint = Console.ReadLine();
if (stringToPrint == "111111")
{
MessageBox.Show("true");
}
else
{
MessageBox.Show("false");
}
return stringToPrint;
}
这是我的 C++ 主函数代码部分,其中进行了调用
CoInitialize(NULL);
MyInterop::IMyDotNetInterfacePtr pDotNetCOMPtr;
HRESULT hRes = pDotNetCOMPtr.CreateInstance(MyInterop::CLSID_MyDotNetClass);
if (hRes == S_OK)
{
BSTR lResult ;
cout << "enter TOTP input" << endl;
_bstr_t bstrStatus = SysAllocString(L"111111");
pDotNetCOMPtr->ShowDialog(bstrStatus,&lResult);
SysFreeString(bstrStatus);
}
CoUninitialize();
system("pause");
这是输出
我面临的问题如下:
- BSTR 字符串在从 C++ 代码传递后未在控制台上返回,尽管我在 C# 中使用返回函数
- 是否可以在控制台上动态插入输入,因为我在这里使用 SysAllocString(""),这使得它有点硬编码。
当您使用 Visual Studio 和 #import 指令时,生成的代码使用 _bstr_t which is a smart wrapper class over BSTR(原始 Windows 类型)。
因此,您不必使用 SysAllocString 或 SysFreeString,您可以很自然地使用 _bstr_t。例如,在您的情况下,如果您的 C# 方法签名是这样的:
public string ShowDialog(string stringToPrint) // you don't need the MarshalAs here, the TLB will build it as a BSTR
那么你可以使用这样的 C++ 代码:
... other imports or includes
// import mscorlib so we have a full generated cool code (I recommend not to use raw_interfaces_only)
// we rename 'or' to something that doesn't pose problems. Your mileage can vary depending on your building context...
#import "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb" rename("or","whatever")
#import "C:\myPath\MyClassLibrary1.tlb" // adapt to your path
int main()
{
CoInitialize(NULL);
{
MyClassLibrary1::_Class1Ptr ptr;
HRESULT hr = ptr.CreateInstance(__uuidof(MyClassLibrary1::Class1)); // should return S_OK/0
_bstr_t input = L"111111";
_bstr_t res = ptr->ShowDialog(input); // assign the return string
wprintf(L"res:%s\n", res.GetBSTR()); // output (unicode) result to console
}
CoUninitialize();
}
你也可以直接这样写:
_bstr_t res = ptr->ShowDialog(L"111111");
// 或这个(自动将 ansi 转换为 unicode)
_bstr_t res = ptr->ShowDialog("111111");
所有 _bstr_t 自动分配和释放。
在处理 com interop 时,我遵循了有关此 link 的教程。代码运行良好,因为我根据我的要求做了一些修改,但是在处理 string.I 时出现了问题我在这里使用 BSTR 字符串作为周边。 这是我从 c++
调用的 c# 函数 public string ShowDialog([MarshalAs(UnmanagedType.BStr)] string stringToPrint)
{
// Console.WriteLine(" Enter TOTP input:");
// stringToPrint = Console.ReadLine();
if (stringToPrint == "111111")
{
MessageBox.Show("true");
}
else
{
MessageBox.Show("false");
}
return stringToPrint;
}
这是我的 C++ 主函数代码部分,其中进行了调用
CoInitialize(NULL);
MyInterop::IMyDotNetInterfacePtr pDotNetCOMPtr;
HRESULT hRes = pDotNetCOMPtr.CreateInstance(MyInterop::CLSID_MyDotNetClass);
if (hRes == S_OK)
{
BSTR lResult ;
cout << "enter TOTP input" << endl;
_bstr_t bstrStatus = SysAllocString(L"111111");
pDotNetCOMPtr->ShowDialog(bstrStatus,&lResult);
SysFreeString(bstrStatus);
}
CoUninitialize();
system("pause");
这是输出
我面临的问题如下:
- BSTR 字符串在从 C++ 代码传递后未在控制台上返回,尽管我在 C# 中使用返回函数
- 是否可以在控制台上动态插入输入,因为我在这里使用 SysAllocString(""),这使得它有点硬编码。
当您使用 Visual Studio 和 #import 指令时,生成的代码使用 _bstr_t which is a smart wrapper class over BSTR(原始 Windows 类型)。
因此,您不必使用 SysAllocString 或 SysFreeString,您可以很自然地使用 _bstr_t。例如,在您的情况下,如果您的 C# 方法签名是这样的:
public string ShowDialog(string stringToPrint) // you don't need the MarshalAs here, the TLB will build it as a BSTR
那么你可以使用这样的 C++ 代码:
... other imports or includes
// import mscorlib so we have a full generated cool code (I recommend not to use raw_interfaces_only)
// we rename 'or' to something that doesn't pose problems. Your mileage can vary depending on your building context...
#import "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb" rename("or","whatever")
#import "C:\myPath\MyClassLibrary1.tlb" // adapt to your path
int main()
{
CoInitialize(NULL);
{
MyClassLibrary1::_Class1Ptr ptr;
HRESULT hr = ptr.CreateInstance(__uuidof(MyClassLibrary1::Class1)); // should return S_OK/0
_bstr_t input = L"111111";
_bstr_t res = ptr->ShowDialog(input); // assign the return string
wprintf(L"res:%s\n", res.GetBSTR()); // output (unicode) result to console
}
CoUninitialize();
}
你也可以直接这样写:
_bstr_t res = ptr->ShowDialog(L"111111");
// 或这个(自动将 ansi 转换为 unicode)
_bstr_t res = ptr->ShowDialog("111111");
所有 _bstr_t 自动分配和释放。