3

在我想在 Delphi 中使用 QImage.bits() 的程序中。因此,在 Qt 中,我创建了一个 dll。下面列出的dll源代码:

测试.h:

  #ifndef TEST_H
    #define TEST_H

    #include "test_global.h"


    extern "C"{
    TESTSHARED_EXPORT uchar* testFunc();
    }


    #endif // TEST_H

测试.cpp:

 #include "test.h"
#include <QtGui>

QImage image;

uchar* testFunc(){
    image.load("c:\\1.png","PNG");
    return (uchar*)image.constBits();
}

在 Delphi 端,我使用此代码来使用 Qt dll:

    function testFunc(): PByteArray; external 'test.dll';
// ...

procedure TForm3.Button1Click(Sender: TObject);
var
  bStream: TBytesStream;
  P: PByteArray;
  Size: Cardinal;
begin
  P := testFunc;
  Size := Length(PAnsiChar(P)); // AnsiChar = 1 Byte
  bStream := TBytesStream.Create();
  try
    bStream.Write(P[0], Size); // Works Fine (^_^)
    bStream.Position := 0;
    bStream.SaveToFile('c:\scr.txt');
  finally
    bStream.Free;
  end;
end;

当我调用 dll 函数时没有返回任何数据!你能帮助我吗?

更新 1: 在实际情况下,我的 Qt 函数非常复杂,由于多种原因,我无法在 Delphi 中编写它。事实上,原始函数从设备中获取屏幕截图并在主内存中处理它。因此,我想将此图像字节发送到 Delphi,以便在 TImage 上显示它,而不将它保存在硬盘和类似的内存上。在本主题中,我刚刚创建了一个简单的类似函数,用于简单的调试和可测试性。是否可以通过为这个问题编写一个真正简单的代码来帮助我?非常感谢你。(-_-)

4

2 回答 2

5

更直接的方法是使用 PByte aka ^Byte,而不是 PByteArray。尽管 TByteArray 是静态类型,但仍然使用数组会增加随机拼写错误的风险,就像使用动态数组一样。


不要使用 PChar - 它会在第一个零字节处停止。图片不是字符串,它可以包含数百个零。

您应该将长度作为单独的变量/函数发送。 int QImage::byteCount () 常量 http://qt-project.org/doc/qt-4.8/qimage.html#byteCount


请编辑你的问题。你问的是 bits 还是 constbits ?这些是不同的属性!


还:

您应该了解编译器、C++ 和 Pascal 中的“调用约定”。您最好能够在汇编程序级别上对其进行跟踪。

尝试在 Pascal 代码中使用“cdecl”指令标记该过程,或者在 C 和 Pascal 代码中使用“stdcall”指令。

尝试使用 FreePascal 的 h2pas 实用程序进行自动转换。


现在最好把 Qt 放在这里。仅仅为了读取 PNG 文件而制作 Qt 桥是非常奇怪和脆弱的。有许多支持 PNG 的原生 Delphi 库。几个例子:

于 2012-09-07T07:18:28.033 回答
2

问题解决了。(^_^)

为了解决它:

在 Qt 端:

测试.h:

#ifndef TEST_H
#define TEST_H

#include "test_global.h"


extern "C"{
TESTSHARED_EXPORT char* testFunc(int &a);
}


#endif // TEST_H

测试.cpp:

#include "test.h"
#include <QtGui>

QImage image;
QByteArray ba;


char* testFunc(int &a){
    image.load("c:\\2.png","PNG");
    QBuffer buffer(&ba);
    buffer.open(QIODevice::WriteOnly);
    image.save(&buffer,"PNG");
    a = ba.size();
    return ba.data();
}

在德尔福方面:

function testFunc(var aByteCount: DWORD): PByte;cdecl external 'test.dll';

// ...
var
  bStream: TBytesStream;
  Size: DWORD;
procedure TForm3.Button1Click(Sender: TObject);
var
  P: PByte;
  s: TStringList;
begin
  Caption := '0';
  P := testFunc(Size);
  bStream := TBytesStream.Create();
  try
    bStream.Write(P[0], Size);
    bStream.Position := 0;
    bStream.SaveToFile('c:\my.png');
  finally
    Caption := IntToStr(Size);
  end;
end;

再次感谢“Arioch The”和“David Heffernan”。(^_^)

于 2012-09-07T13:09:58.450 回答