我在VS2010中使用Robert Giesecke Unmanaged Exports 1.2.6,我的目标是将一系列结构从c#(.NET 3.5)传递给delphi(D7).我不得不承认,我对德尔福并不熟悉.
我已经阅读过这篇文章,但建议的答案对我不起作用:当func在delphi中调用时,CPU调试窗口打开,如果我继续应用程序退出,无异常且没有所需的结果.
这是我试过的代码:
C#平台x86
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
namespace ArrayTest
{
public class Class1
{
public struct Sample
{
[MarshalAs(UnmanagedType.BStr)]
public string Name;
}
[DllExport]
public static int func(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
Sample[] samples,
ref int len
)
{
// len holds the length of the array on input
// len is assigned the number of items that have been assigned values
// use the return value to indicate success or failure
for (int i = 0; i < len; i++)
samples[i].Name = "foo: " + i.ToString();
return 0;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Delphi7中
program DelphiApp;
{$APPTYPE CONSOLE}
uses
SysUtils,
ActiveX;
type
TSample = record
Name: WideString;
end;
PSample = ^TSample;
function func(samples: PSample; var len: Integer): Integer; stdcall;
external 'ArrayTest.dll';
procedure Test2;
var
samples: array of TSample;
i, len: Integer;
begin
len := 10;
SetLength(samples, len);
if func(PSample(samples), len)=0 then
for i := 0 to len-1 do
Writeln(samples[i].Name);
end;
begin
Test2();
end.
Run Code Online (Sandbox Code Playgroud)
如前所述,调试器打开CPU窗口,如果我继续应用程序退出,无异常或错误消息.如果我在没有dbugger的情况下运行它,Windows告诉我应用程序不再工作,应用程序关闭.
我错过了什么?
更新
修改后的代码
[DllExport]
public static int func(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
Sample[] samples,
ref int len
)
{
Console.WriteLine("return 0");
return 0;
}
procedure Test2;
var
samples: array of TSample;
i, len: Integer;
begin
len := 10;
SetLength(samples, len);
if func(PSample(samples), len)=0 then
for i := 0 to len-1 do
Writeln('D7: ', i);
end;
Run Code Online (Sandbox Code Playgroud)
即使我不访问任何一侧的阵列,行为仍然是相同的.
控制台输出: return 0
好像我发现了这个问题:
如果使用.NET 4.0或更高版本,代码运行正常.如果使用.NET 3.5或更低版本,则len-parameter必须按值传递.
请参阅MSDN文档SizeParamIndex v3.5:
包含大小的参数必须是按值传递的整数.
请参阅MSDN文档SizeParamIndex v4.0:
当数组作为C样式数组传递时,封送程序无法确定数组的大小.因此,要将托管数组传递给非托管函数或方法,必须提供两个参数:
数组,由引用或值定义.
数组大小,由引用或值定义.
C#
[DllExport]
public static int func(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
Sample[] samples,
int len,
ref int outLen
)
{
// len holds the length of the array on input
// outLen is assigned the number of items that have been assigned values
// use the return value to indicates success and the required array size (>=0) or failure (<0)
int requiredSize = 20;
if (requiredSize < len)
{
len = requiredSize;
}
for (outLen = 0; outLen < len; outLen++)
{
samples[outLen].Name = "foo: " + outLen.ToString();
}
return requiredSize;
}
Run Code Online (Sandbox Code Playgroud)
Delphi7中
function func(samples: PSample; len: Integer; var outLen: Integer): Integer; stdcall;
external 'ArrayTest.dll';
procedure Test2;
var
samples: array of TSample;
i, len: Integer;
begin
len := 0;
// query the required array size
i := func(PSample(samples), len, len);
if i>0 then
begin
len := i;
SetLength(samples, len);
if func(PSample(samples), len, len)>=0 then
for i := 0 to len-1 do
Writeln(samples[i].Name);
end;
end;
Run Code Online (Sandbox Code Playgroud)
张贴在我的问题和大卫·赫弗南发布的代码在这里只适用于.NET> = 4.0! 如果必须使用.NET <= 3.5,则必须按值传递数组,而不是按引用传递!
| 归档时间: |
|
| 查看次数: |
1390 次 |
| 最近记录: |