1
在SO和网上有很多很棒的信息(例如pinvoke.net),它描述了从托管代码调用非托管代码。我处于一种独特的情况,我需要为原有的VB6应用程序实现一个API,该应用程序由于商业原因而无法更改。为了简洁起见,可以说VB6应用程序执行以下操作。VB6到托管C#方法的C++/CLI包装器
'Legacy VB6
Public Declare Function GetData Lib "NewDLL" (ByVal szDataID As String,
ByRef DataStruct As TDataStruct) As Long
Type TDataStruct
szSKU As String * 10
szTypeInfo As String * 20
End Type
这是我如何接近它。
C++/CLI实现。
//NewDLL.h
typedef struct DATASTRUCT
{
char szSKU [10];
char szTypeInfo [20];
];
//NewDLL.cpp - C++/CLI
#include "NewDLL.h"
using namespace System;
extern "C" __declspec(dllexport)
Int32 __stdcall GetData(LPTSTR szDataID, DATASTRUCT* dataStruct)
{
String^ m_DataID;
m_DataID = gcnew String(szDataID);
NewDotNetDll::GetDataClass::GetData(m_DataID, dataStruct);
return (true);
}
.NET实现。
//DataStruct.cs
using etc...
using System.Runtime.InteropServices;
namespace NewDotNetDll
{
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct DataStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string SkuID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string TypeInfo;
}
}
//GetDataClass.cs
using etc...
using System.Runtime.InteropServices;
namespace NewDotNetDll
{
public class GetDataClass
{
public static Int32 GetData(
[MarshalAs(UnmanagedType.LPStr)] string skuID,
[Out, MarshalAs(UnmanagedType.LPStruct)] DataStruct dataStruct)
{
Int32 rc = 0;
//to do...
return rc;
}
}
}
问题 - 怎样才能通过引用,以便它可以在内存中,非托管结构起到通过VB的TDataStruct我的C#方法?在此先感谢大家。
卢卡斯,太感谢你了。我仍然遇到一个小问题 - 当我构建我的C++/CLIP包装器时,错误C2664不能将参数2从'DATASTRUCT *'转换为'NewDotNetDll :: DataStruct *'。我的托管DataStruct已根据您的建议进行了修改 - 它不包含托管类型。 – 8Pod
哦,是的,我忽略了这一点。你必须施放:'reinterpret_cast(dataStruct)'应该做到这一点(因为类型与编译器无关)。 –
卢卡斯 - 非常感谢你! – 8Pod