Compatibilidad rddads / X# RDD
ace64.dll / ace32.dll de OpenADS es reemplazo directo del
Advantage Client Engine. Dos RDDs de terceros enlazan contra ella
por nombre:
- Harbour
contrib/rddads— cubierto end-to-end desde v0.1.0-rc1. AXDBFCDXde X# (ADSRDD.prg) — cubierto local + sobre la red desde v1.0.0-rc19 (M12.22 / M12.23).
Cómo X# vincula OpenADS
ADSRDD.prg hace LoadLibrary("ace32.dll") y resuelve cada entry
point por nombre vía GetProcAddress. El RDD Advantage de X#
llama a una superficie mucho más amplia que contrib/rddads,
incluyendo overloads versionadas (AdsCreateTable90,
AdsCreateIndex90, etc.) que absorben los parámetros charset /
collation / page-size añadidos en builds recientes de ACE.
OpenADS exporta todos los nombres Ads*NN que X# busca; la
mayoría reenvían a la signatura base, unos cuantos son
accept-and-ignore para toggles que no aplican a una
implementación clean-room, y los genuinamente no-implementados
devuelven AE_FUNCTION_NOT_AVAILABLE para que el runtime de X#
caiga a su propio path cliente.
M12.22 — overloads versionadas de ACE
| Export | Comportamiento |
|---|---|
AdsConnect26 |
Reenvía a AdsConnect60. |
AdsCreateTable71 / AdsCreateTable90 |
Reenvían a AdsCreateTable (descartan charset / collation / page-size). |
AdsOpenTable90 |
Reenvía a AdsOpenTable80. |
AdsCreateIndex90 |
Reenvía a AdsCreateIndex61 tras re-mapear flags. |
AdsDDAddTable90 |
Reenvía a AdsDDAddTable. |
AdsDDCreateRefIntegrity62 |
Reenvía a AdsDDCreateRefIntegrity. |
AdsFindFirstTable62 / AdsFindNextTable62 |
Reenvían a base. |
AdsGetDateFormat60 |
Reenvía a AdsGetDateFormat. |
AdsGetExact22 |
Reenvía a AdsGetExact. |
AdsReindex61 |
Reenvía a AdsReindex. |
AdsRestructureTable90 |
Reenvía a AdsRestructureTable. |
AdsGetBookmark60 / AdsGotoBookmark60 |
Round-trip del recno como blob de 4 bytes. |
AdsCancelUpdate90 / AdsSetProperty90 |
No-ops aceptados. |
AdsFindConnection25 / AdsGetTableHandle25 |
Reportan not-found — OpenADS indexa por handle, no por path / nombre. |
M12.23 — cierre del gap de exports X#
Una ejecución viva de AXDBFCDX contra la DLL OpenADS surfaceó
~45 entry points más que ADSRDD.prg busca. Comportamiento:
- Field setters (
AdsSetField,AdsSetEmpty,AdsSetNull,AdsSetShort,AdsSetMoney,AdsSetTime,AdsSetTimeStamp) — todos manejan el idiom ACE “nombre de campo o ordinal 1-based cast a puntero” (el_FieldSubde X# llama aAdsGetFieldType/Length/Decimalspor ordinal, pasando un valor de puntero pequeño que el código viejo desreferenciaba como string). - Field readers (
AdsGetDate,AdsGetMemoBlockSize,AdsGetTableOpenOptions,AdsGetBookmark) — implementaciones reales. - Helpers de cursor (
AdsCancelUpdate,AdsContinue,AdsEval*Expr) —AdsCancelUpdatees accept-and-ignore; los demás devuelvenAE_FUNCTION_NOT_AVAILABLEy X# cae al fallback. - Toggles RI / unique / autoinc — accept-and-ignore (la
aplicación real ocurre vía
AdsCreateIndex/ DD). - Helpers
AdsStmt*—AE_FUNCTION_NOT_AVAILABLE; la superficie SQL de X# los rodea.
Fixes de semántica que llegaron con M12.23
Parecían “exports faltantes” desde X#, pero eran comportamiento incorrecto en entries existentes:
AdsAppendRecordauto-bloquea el nuevo registro. Semántica ACE para tablas no exclusivas — elGoHotde X# rehúsa escribir un registro que ve como no bloqueado.AdsIsRecordLocked/AdsLockRecord/AdsUnlockRecordhonranrecno == 0= registro actual y reportan el estado real del lock en vez de devolver0.- Fix bit de opción
AdsCreateIndex61/AdsCreateIndex90. El flag “descending” esADS_DESCENDING(0x08), no0x02—0x02esADS_COMPOUND, que el ADSRDD de X# siempre setea para órdenes CDX, así que la máscara vieja construía cada orden descendente yDbGoTopaterrizaba en la última key. AdsCreateTable/AdsCreateTable90crean un.fptvacío junto al.dbfcuando la lista de campos tieneM(usandousMemoBlockSize, default 64). Sin élConnection::open_tableno puede adjuntar memo store y todo write de memo falla “memo store not attached”.
X# remoto (M12.23, rc19)
Tres fixes más para que ADSRDD de X# pilote openads_serverd por
la red (AdsConnect60("tcp://host:puerto/<datadir>",
ADS_REMOTE_SERVER) → AX_SetConnectionHandle → DbUseArea):
remote_field_indexhonra el idiom “nombre de campo O ordinal 1-based cast a puntero” — igual que el lado local.- El branch remoto de
AdsOpenTableañade.dbfpor defecto si falta la extensión (X# pasa el nombre pelado para tablas remotas). AdsGetTableFilenameadquirió ruta remota (devuelve el nombre abierto) en lugar de fallarAE_INTERNAL_ERROR— elOpende X# lo llama justo tras_FieldSub.
Harness de tests
tests/smoke/xsharp/
├── AdsSmoke.prg # local: ace64.dll directo
└── AdsSmoke_remote.prg # remoto: openads_serverd por tcp://
Ambos pasan end-to-end. Doctest:
tests/abi_versioned_overloads_test.cpp (local) y
tests/abi_remote_overloads_test.cpp (sobre red, gated en
-DOPENADS_TEST_REMOTE=ON).
Follow-ups rc20+ desde feedback X#
- rc21 / M12.24 —
AdsGetLastTableUpdatecon signatura real matching ACE;AdsSetDateFormatya no es no-op;AdsSetAOFretorna éxito +ADS_OPTIMIZED_NONEen expresiones no optimizables. - rc22 / M12.25 —
AdsCreateTableestampa la fecha de hoy en el header DBF, así que un create+open fresco reporta hoy en vez de1900-00-00hasta el primerDbAppend.