2

我在 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 long j, ref long k );

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

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

谢谢。

4

3 回答 3

3

StringBuilder如果在 C#中将可修改的 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

请注意,VB6Long已转换为IntegerVB6Integer已转换为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 声明的准确翻译,应该具有相同的行为。如果这仍然不起作用,那么也许您可以描述它到底是如何不起作用的(是否曾经调用过非托管函数,参数是否垃圾,返回值是否垃圾,还有其他什么?)。

于 2010-01-04T13:08:23.323 回答
2

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

于 2010-01-04T13:09:37.377 回答
1

如果 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 代码。在此处阅读有关 MSDN 的更多信息。

免责声明:JaredPar确实应该为这个答案获得任何代表点,因为他编写了一些工具

于 2010-01-04T15:16:59.040 回答