You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于.pas构建的libZXing.a在C++Builder安卓项目中运行异常排查

问题描述

我在Android项目中尝试使用C++Builder 11.2将Delphi的ZXing.Delphi库.pas文件生成的libZXing.a静态库。运行项目时,IDE无法启动调试模式,设备显示黑屏;重试则弹出错误:Can't bind address: Address already use. Exiting.。移除该库后,链接器会报库文件的未定义引用错误。

我已通过CBuilder静态库项目为Android构建了libZXing.a,并将其添加到Android应用项目中,同时将IDE生成的.pas对应的.hpp文件路径加入包含目录。项目中包含一个调用该库方法的.pas单元,且已遵循CBuilder调用Delphi代码的规范,项目编译成功但运行失败。

请问:

  1. 这种构建libZXing.a的方式是否可行?
  2. 我的Delphi代码调用方式是否存在错误或遗漏?

调用libZXing.a的Pascal单元代码

unit uZXing;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.Math.Vectors, System.Actions, System.Threading, System.Permissions,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects, FMX.StdCtrls, FMX.Media, FMX.Platform, FMX.MultiView, FMX.ListView.Types,
  FMX.ListView, FMX.Layouts, FMX.ActnList, FMX.TabControl, FMX.ListBox, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, FMX.Controls3D, FMX.Memo.Types,
  ZXing.BarcodeFormat, ZXing.ReadResult, ZXing.ScanManager;

type
  IMyDelphiInterface = interface
    procedure ParseImage(fScanInProgress: Boolean; fScanBitmap: TBitmap; lblScanStatus: TLabel; strList: TStringList);
  end;

  function ZXing_DelphiInstance() : IMyDelphiInterface;

implementation

type
  TDelphiClassImplementingInterface = class(TInterfacedObject, IMyDelphiInterface)
    public
    procedure ParseImage(fScanInProgress: Boolean; fScanBitmap: TBitmap; lblScanStatus: TLabel; strList: TStringList);
  end;

function ZXing_DelphiInstance() : IMyDelphiInterface;
begin
  Result := TDelphiClassImplementingInterface.Create;
end;

procedure TDelphiClassImplementingInterface.ParseImage(fScanInProgress: Boolean;
  fScanBitmap: TBitmap; lblScanStatus: TLabel; strList: TStringList);
begin
  TThread.CreateAnonymousThread(
    procedure
    var
      ReadResult: TReadResult;
      ScanManager: TScanManager;
    begin
      fScanInProgress := True;
      ScanManager := TScanManager.Create(TBarcodeFormat.Auto, nil);
      try
        try
          ReadResult := ScanManager.Scan(fScanBitmap);
        except
          on E: Exception do
          begin
            TThread.Synchronize(TThread.CurrentThread,
              procedure
              begin
                lblScanStatus.Text := E.Message;
              end);
            exit;
          end;
        end;
        TThread.Synchronize(TThread.CurrentThread,
          procedure
          begin
            if (Length(lblScanStatus.Text) > 10) then
            begin
              lblScanStatus.Text := '*';
            end;
            lblScanStatus.Text := lblScanStatus.Text + '*';
            if (ReadResult <> nil) then
            begin
              strList.Add(ReadResult.Text);
            end;
          end);
      finally
        if ReadResult <> nil then
          FreeAndNil(ReadResult);
        ScanManager.Free;
        fScanInProgress := false;
      end;
    end).Start();
end;

end.

C++Builder调用Delphi代码的实现

_di_IMyDelphiInterface DI_ZXing { ZXing_DelphiInstance() };
TStringList *strList;

TThread::Synchronize(TThread::CurrentThread,
[this, DI_ZXing, strList]() {
    CameraComponent1->SampleBufferToBitmap(imgCamera->Bitmap, True);
    if(fScanInProgress)
        exit;
    fFrameTake++;
    if(fFrameTake % 4 != 0)
        exit;
    if(fScanBitmap)
        fScanBitmap->DisposeOf();
    fScanBitmap = new TBitmap;
    fScanBitmap->Assign(imgCamera->Bitmap);
    DI_ZXing->ParseImage(fScanInProgress, fScanBitmap, Form_TabbedTemplate->LabelCapachos_OBRScan, strList);
});

问题解答

一、构建libZXing.a的方式可行性

这种方式理论上可行,CBuilder支持将Delphi代码编译为静态库供C项目调用,但需注意以下关键前提:

  • 静态库的目标Android架构(如armeabi-v7a、arm64-v8a)必须与应用项目完全一致,混合架构会导致运行时崩溃或链接错误。
  • 确认ZXing.Delphi库无Windows专属代码,完全兼容Android平台的FMX框架。
  • 静态库与应用项目的编译选项(RTTI、异常处理、Unicode设置等)需保持一致,否则会出现调用兼容性问题。

二、调用代码中的错误与遗漏

1. Pascal代码问题

  • 参数传递错误:fScanInProgress是按值传递的Boolean参数,在ParseImage中修改它不会同步到外部变量。需改为按引用传递(var fScanInProgress: Boolean),否则外部的扫描状态判断会完全失效,引发线程堆积。
  • Bitmap资源泄漏:C++端创建的fScanBitmap传递到Pascal后未被释放,长期运行会导致内存溢出,引发黑屏。需明确资源释放责任,可在Pascal代码扫描完成后调用fScanBitmap.Free。
  • TStringList线程不安全:strList在跨线程环境中被操作,未加同步锁,容易引发竞态条件,导致数据错乱或崩溃。

2. C++代码问题

  • 未初始化的strList:TStringList *strList;仅声明未初始化,直接传递会触发空指针访问,导致崩溃。必须先执行strList = new TStringList;初始化。
  • 冗余的线程同步:C端已在TThread::Synchronize中阻塞UI线程执行代码,Pascal端又创建匿名线程处理扫描,双重同步会导致UI线程长期阻塞,引发黑屏。应将C端的同步逻辑改为异步执行。
  • 共享变量线程可见性:fScanInProgress作为跨线程共享变量,未声明为volatile或使用同步机制,线程间无法正确同步其值,会导致扫描逻辑混乱。
  • 调试端口冲突:Can't bind address: Address already use错误多因之前的调试进程未正常退出占用端口,可尝试重启IDE和设备,或在项目设置中修改调试端口。

内容的提问来源于stack exchange,提问作者PCSdeZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 15:59:56