我有一些客户使用 VB6 和其他一些语言的应用程序。该代码使用 OLE (COM) 运行良好,但客户更喜欢使用 native DLL 以避免注册库并将它们部署到现场。
当我注册 DLL 并在 VB6 (OLE) 中进行测试时,它工作正常。当我调用一个返回 Strutc 的方法时,它与 OLE 一起工作正常,但是,如果我使用 Declare 在 VB6 中访问,我在应该返回相同类型结构的方法中遇到 fatal error (方法“EchoTestData”见下文)。
代码在 C# 中编译,以在非托管代码中使用 OLE 或通过入口点>我用 VB6 测试过。
namespace TestLib
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("TestClass")]
public class TestClass : System.EnterpriseServices.ServicedComponent
{
/*
* NOTE:
* ExportDllAttribut: a library that I have used to publish the Entry Points,
* I had modified that project and it works fine. After complile, the libray
* make the entry points...
* http://www.codeproject.com/Articles/16310/How-to-Automate-Exporting-NET-Function-to-Unmanage
*/
/*
* System.String: Converts to a string terminating in a null
* reference or to a BSTR
*/
StructLayout(LayoutKind.Sequential)]
public struct StructEchoData
{
[MarshalAs(UnmanagedType.BStr)]
public string Str1;
[MarshalAs(UnmanagedType.BStr)]
public string Str2;
}
/*
* Method static: when I use this method, the Vb6 CRASH and the EVENT VIEWER
* show only: System.Runtime.InteropServices.MarshalDirectiveException
* HERE IS THE PROBLEM in VB6 with declare...
* Return: struct of StructEchoData type
*/
[ExportDllAttribute.ExportDll("EchoTestStructure", CallingConvention.StdCall)]
public static StructEchoData EchoTestStructure(string echo1, string echo2)
{
var ws = new StructEchoData
{
Str1 = String.Concat("[EchoTestData] Retorno String[1]: ", echo1),
Str2 = String.Concat("[EchoTestData] Retorno String[1]: ", echo2)
};
return ws;
}
/*
* Method NOT static: it is used as COM (OLE) in VB6
* In VB6 it returns very nice using with COM.
* Note that returns the StructEchoData without problems...
* Return: struct of StructEchoData
*/
[ExportDllAttribute.ExportDll("EchoTestStructureOle", CallingConvention.StdCall)]
public StructEchoData EchoTestStructureOle(string echo1, string echo2)
{
var ws = new StructEchoData
{
Str1 = String.Concat("[EchoOle] Return StringOle[1]: ", echo1),
Str2 = String.Concat("[EchoOle] Return StringOle[2]: ", echo2),
};
return ws;
}
/*
* Method static: It works very nice using 'Declare in VB6'
* Return: single string
*/
[ExportDllAttribute.ExportDll("EchoS", CallingConvention.StdCall)]
// [return: MarshalAs(UnmanagedType.LPStr)]
public static string EchoS(string echo)
{
return "[TestClass::EchoS from TestLib.dll]" + echo;
}
/*
* Method NOT static: it is used as COM (OLE) in VB6
* In VB6 it returns very nice
* Return: single string
*/
[ExportDllAttribute.ExportDll("EchoSOle", CallingConvention.StdCall)]
// [return: MarshalAs(UnmanagedType.LPStr)]
public string EchoSOle(string echo)
{
return "[TestClass::EchoS from TestLib.dll]: " + echo;
}
}
}
现在,在 VB6 中,我无法使用 Declare 或将 TestLib.Dll 注册为 COM 进行测试
在 VB6 中使用 DECLARE:
Private Declare Function EchoS Lib "C:\Temp\_run.dll\src.app.vb6\TestLib.dll"_
(ByVal echo As String) As String
Private Type StructEchoData
Str1 As String
Str2 As String
End Type
Private Declare Function EchoTestStructure Lib "C:\Temp\_run.dll\src.app.vb6\TestLib.dll"_
(ByVal echo1 As String, ByVal echo2 As String) As StructEchoData
// ERROR - CRASH VB6
Private Sub EchoData_Click()
Dim ret As StructEchoData
ret = EchoTestStructure("echo1 Vb6", "echo2 vb6")
TextBox.Text = ret.Str1
End Sub
// WORKS Fine, returns a string
Private Sub btRunEchoTestLib_Click()
TextBox.Text = EchoS("{Run from VB6}")
End Sub
并在 OLE 中使用 VB6:
1圣。注册 DLL:C:\Windows\Microsoft.NET\Framework\v4.0.30319\regsvcs.exe TestLib.dll/tlb:Test.tlb
第二。在项目中添加引用。程序运行,我得到了一个字符串的响应,并在也有一个结构时收到了响应。
Private Sub Echo_Click()
Dim ResStr As String
Dim obj As TestLib.TestClass
Set obj = New TestClass
ResStr = obj.EchoSOle(" Test message")
MsgBox "Msg Echo: " & ResStr, vbInformation, "ResStr"
Beep
End Sub
Private Sub EchoDataOle_Click()
Dim obj As TestLib.TestClass
Set obj = New TestClass
// Here I define the struct and works fine!!
Dim ret As TestLib.StructEchoData
ret = obj.EchoTestStructureOle("test msg1", "test msg2")
TextStr1.Text = ret.Str1
TextStr2.Text = ret.Str2
Debug.Print ret.Str1
Debug.Print ret.Str2
Beep
End Sub
因此,StructEchoData 使用 COM 包装得很好,但如果我想使用 Declare 并通过入口点获得访问权限,则行不通。有没有人可以提出任何建议?
最佳答案
VB6 Declare Lib
仅适用于未管理的 DLL 导出函数。 C# 不会将其函数公开为非托管函数,因为它是托管代码。从 C# 导出类的唯一支持方法是使用 COM。因此,您不能使用 Declare Lib
从 VB6 访问 C# 方法。
有一个库可以从您的 C# 代码中创建不受管理的导出;罗伯特·吉塞克的 Unmanaged Exports .我个人从未使用过它;我只在 Stack Overflow 上看到过它。
有一种支持从 .Net 程序集导出非托管函数的方法,它使用 C++/CLR,因为它允许混合托管代码和非托管代码。您可以创建一个 C++/CLR 包装器,该包装器导出调用 C# DLL 的非托管函数。这就是我要走的路。
关于c# - 将结构传递给非托管代码,从 C# DLL 到 VB6,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27725139/