【问题标题】:Converting dllimport from vb6 to c# 3.5将 dllimport 从 vb6 转换为 c# 3.5
【发布时间】:2011-01-01 05:57:45
【问题描述】:

我在 VB6 中有一些从 dll 导入函数的代码,它使用 byVal 和 byRef 关键字,我想将该代码转换为 C# 3.5。

  1. 字符串的unicode编码会有问题吗?

  2. 我是否将 vb6 中的“byRef”变量声明为 C# 代码中的“ref”变量?

  3. 它将返回值输入到由 VB6 代码作为“byVal”参数发送的字符串中,这是如何工作的,如果你想允许的话,你不应该发送东西“byRef”吗?编辑字符串的功能?这个概念仍然适用于我的 C# 代码吗?

我尝试从 VB6 处理函数声明,参数类型只是 int、long 和 string。在有“byVal”关键字的地方,我只是将其留空并用 C# 中的“ref”关键字替换了“byRef”关键字,代码不起作用。

VB6 代码:

Private Declare Function Foo Lib "Foo_Functions.dll" (ByVal a as String, ByVal b
as Long, ByVal c as String, ByVal d as String, ByVal e as String, ByVal f
as String, ByVal g as Long, ByVal h as String, ByVal i as String, ByRef j
as Long, ByRef k as Long) As
Integer

我的 C# 3.5 翻译:

[Dllimkport("foo_functions.dll")] public static extern int foo(String a, long b,
string c, string d, string e, string f, long g, string h, stringbuilder i,
ref长 j,参考长 k);

请帮忙,我已经花了一整天的时间:p....

最后,我使用自动项目转换器(从 VB6 到 VB.NET 2008)将函数调用转换为 VB.NET 库,并使用 C# 引用调用它。

谢谢。

【问题讨论】:

  • 如果您在问题中包含导入函数的 VB6 声明,我可能会有所帮助。没有任何代码可以正常工作,因此很难正确理解您要做什么。
  • 您是否尝试从 c# 调用 win32 dll 中的函数?
  • 另请注意,VB6 中的 Long 变量与 C# 中的 Int32 (int) 相同。
  • 我建议将原始语言(很可能是 C)的原始 DLL 函数声明粘贴到您的问题中。我建议只是因为在 VB6 中经常导入像 Integer 这样的东西,而在 C# b/c 中它真的应该是 Int32 时,原来的 C 返回了一个 HANDLE。除非我们得到最原始的,否则很难说。

标签: c# vb6 interop dllimport vb6-migration


【解决方案1】:

如果在 C# 中用 StringBuilder 替换它们,可修改的 byVal 字符串应该可以工作。 另一种可能的解决方案是使用[MarshalAs(UnmanagedType.VBByRefStr)] ref string i

我在 Visual Studio 中使用了“升级 Visual Basic 6 代码...”工具,这导致了以下 VB.NET 代码:

Private Declare Function Foo Lib "Foo_Functions.dll" (ByVal a As String, _
  ByVal b As Integer, ByVal c As String, ByVal d As String, ByVal e As _
  String, ByVal f As String, ByVal g As Integer, ByVal h As String, ByVal i _
  As String, ByRef j As Integer, ByRef k As Integer) As Short

请注意,VB6 Long 已转换为 Integer,而 VB6 Integer 已转换为 Short。 然后我使用反射器查看它在 C# 中的样子:

[DllImport("Foo_Functions.dll", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
private static extern short Foo([MarshalAs(UnmanagedType.VBByRefStr)] ref
  string a, int b, [MarshalAs(UnmanagedType.VBByRefStr)] ref string c,
  [MarshalAs(UnmanagedType.VBByRefStr)] ref string d,
  [MarshalAs(UnmanagedType.VBByRefStr)] ref string e,
  [MarshalAs(UnmanagedType.VBByRefStr)] ref string f, int g,
  [MarshalAs(UnmanagedType.VBByRefStr)] ref string h,
  [MarshalAs(UnmanagedType.VBByRefStr)] ref string i, ref int j, ref int k);

这是 VB6 声明的准确翻译,应该具有相同的行为。如果这仍然不起作用,那么也许您可以描述它到底是如何不起作用的(是否曾经调用过非托管函数,参数是否垃圾,返回值是否垃圾,还有其他什么?)。

【讨论】:

  • 尝试 VBByRefStr 变体,如果需要,还可以将 CharSet=CharSet.Unicode 添加到 DllImport 属性。
  • 我转换了原始代码 VB6 -> VB.NET -> C# 并得到了这个声明,也许这行得通?
【解决方案2】:

看看www.pinvoke.net 它显示了 C# 和 VB.net 示例。

【讨论】:

  • 据我了解,此工具仅用于调用连接到windows操作系统的dll,而不是自定义的。
  • 是的,你是对的。它有各种针对 windows API 等的 dllImport 调用示例。这些示例可以帮助您将 VB 转换为 C#。
  • 这些示例将帮助您将 VB.Net 转换为 C#,而不是 VB6。 OP 需要将 VB6 转换为 C#。
  • @MarkJ:当然,我的回答更多是关于 dll 导入的示例,这可能会有所帮助,因为人们可能只是在寻找这些语言中的任何一种的解决方案或示例,而不是直接/特定的转换。
【解决方案3】:

如果 VB6 Declare 语句包含 ByVal s As String,则该参数将被编组为指向 ANSI 字符串的指针。我会尝试将 DLLImport 更改为 [DllImport("Foo_Functions.dll", CharSet=CharSet.Ansi)]

对于输出参数,您需要使用StringBuilder s 并预初始化足够大的 StringBuilder 以容纳输出。输入参数可以使用String s

您有 DLL 的 C 声明吗? Mabe 在原始供应商的文档中,还是在 DLL 源代码中?如果是这样,有一个免费工具CLRInsideOut 可以将该 C 声明转换为 C# 或 VB.Net PInvoke 代码。阅读更多on MSDN here

免责声明:JaredPar 应该真的得到这个答案的任何代表点,因为他 wrote some of the tool

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-29
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多