How do I use complex data structures with `ffi`, `ref-struct`, and `ref-array`?

888 Views Asked by At

I am working on a project that uses ffi to interact with a compiled C library. I am trying to get some complex data structures to work and am having problems figuring out the proper way to get values inside these data structures. I have two instances I'm trying to figure out. I am not a C guy so I'm winging it on that end.

Instance 1

There is a C struct that contains properties that are, what look like pointers to character arrays. Here's the C-code that defines the struct:

#define RPC_STRING_LENGTH           32
#define RPC_STRING_LENGTH_CALLID    128
typedef struct {
    E_CALL_STATE eCallState;
    BOOL bInboundCall;
    BOOL bVideoCall;
    BOOL bRecording;
    BOOL bEncrypted;
    BOOL bHDAudio;
    BOOL bVirtualMeetingCall;
    E_PROTOCOL_CODEC eCurrentCodec;
    E_PROTOCOL_ALERT_INFO_CALL_TYPE eAlertInfoType;
    double dAccumulatedMOSLQ;
    int  nVideoState;
    int  nErrorCode;
    unsigned int nCallStartTime;
    char cPhoneNumber[RPC_STRING_LENGTH];
    char cName[RPC_STRING_LENGTH];
    char cCallId[RPC_STRING_LENGTH_CALLID];
    char cPreviousCallId[RPC_STRING_LENGTH_CALLID];
} RPC_CALL_STATE;

Now, I've been able to successfully extract the E_CALL_STATE value and the BOOL properties but I'm having difficulty getting the strings stores in cPhoneNumber, cName, cCallId, and cPreviousCallId. Here's how I have the it setup using ref-struct:

import ref from 'ref';
import StructType from 'ref-struct';

const RPC_CALL_STATE = StructType({
    eCallState: ref.types.int,
    bInboundCall: ref.types.bool,
    bVideoCall: ref.types.bool,
    bRecording: ref.types.bool,
    bEncrypted: ref.types.bool,
    bHDAudio: ref.types.bool,
    bVirtualMeetingCall: ref.types.bool,
    dAccumulatedMOSLQ: ref.types.double,
    nVideoState: ref.types.int,
    nErrorCode: ref.types.int,
    nCallStartTime: ref.types.uint,
    cPhoneNumber: ref.types.char,
    cName: ref.types.char,
    cCallId: ref.types.char,
    cPreviousCallId: ref.types.char,
});

Here's the Javascript that interprets this struct (for reference, RPC_CALL_STATE is an externally defined enum):

pDataRef = ref.reinterpret(pData, RPC_CALL_STATE.size);
pDataRef.type = RPC_CALL_STATE;
const callProgressStruct = ref.get(pDataRef);

If I look at the value stored on callProgressStruct.cPhoneNumber, I get 0. So, a few questions:

  • What is the correct ref.types to use here?
    • Is char correct?
    • If not, what should this be?
  • How do I extract the actual string value stored in cPhoneNumber?
  • Is there a way to use ref-array here?

Instance 2

I have a C struct that is defined as such:

typedef struct AUDIO_OS_DEVICES {
    int nNumberDevices;
    AUDIO_OS_DEVICE *pDevices;
} AUDIO_OS_DEVICES;

In this code, *pDevices ends up being an array of AUDIO_OS_DEVICE structs. Those structs are defined in C as:

typedef struct AUDIO_OS_DEVICE {
    int deviceId;
    int deviceFlags;
    char deviceName[AUDIO_OS_DEVICE_NAME_MAX_LEN];
    char deviceUID[AUDIO_OS_DEVICE_UID_MAX_LEN];
    char manufacturerName[AUDIO_OS_DEVICE_MANUFACTURER_MAX_LEN];
} AUDIO_OS_DEVICE;

In Javascript I have this setup using ref-struct:

const AUDIO_OS_DEVICE = StructType({
  deviceId: ref.types.int,
  deviceFlags: ref.types.int,
  deviceName: ref.types.char,
  deviceUID: ref.types.char,
  manufacturerName: ref.types.char,
});

const AUDIO_OS_DEVICES = StructType({
    nNumberDevices: ref.types.int,
    pDevices: [???],
});

I have no idea what type to cast pDevices to here nor do I know how to extract the array of AUDIO_OS_DEVICE structs. I am also hitting the issue already described with character arrays.

Any help would be appreciated. I'm at a dead-end until I can figure this out.

0

There are 0 best solutions below