How to access External Fixed size C array in Swift?

Hi,

Overview:

  • I have a C file which contains a fixed size array a1 which I would like to access from Swift.
  • There is a corresponding header file in which a1 is declared as external
  • I have included the header file in the bridging header.

Problem:

  • The external fixed size array a1 declared in the header file is not accessible in main.swift.
  • The problem occurs only when the header file declares the array as external instead of defining it in the header file.

In the following scenarios there are no compilation errors:

  • Accessing the int variable i1.
  • When the array a1 is defined in the header file instead of marking it as extern in header, then there is no compilation error.

Question:

  • What should I do to make it accessible ?
  • Am I missing something ?

Thanks.

Code:

main.swift

import Foundation

print(i1) //This compiles fine
//print(a1) //Compilation Error: Use of unresolved identifier 'a1'

Car.h

#ifndef Car_h
#define Car_h

extern int i1;
extern int a1[]; //external array is what is causing the issue

#endif /* Car_h */

Car.c

#include "Car.h"

int i1 = 20;
int a1[] = { 1, 2, 3};

TestC-Bridging-Header.h

#include "Car.h"

Note: I have edited the question, to isolate the problem.

This probably ought to work (I think we should import a1 as UnsafeMutablePointer<CInt>, but it looks like we simply don't). As a work-around you can make explicit that it's "really just a pointer":

car.h
extern int i1;
extern int *a1p;

car.c
int a1[] = { 1, 2, 3 };
int a1p = a1;

main.swift
// a1p is imported as UnsafeMutablePointer<CInt>!
a1p[1] // 2

If you can spare a few moments, this would be worth writing up on bugs.swift.org. Otherwise, I'll probably do so sometime later today.

1 Like

@scanon Thanks a ton!!! I was breaking my head over it.

Just curious, is there a reason why extern int a1[]; wasn't accessible ? Is it a bug ?

Note: I have edited the question, to highlight what works.

I haven't investigated, but my guess is that the importer simply doesn't implement support for array-of-unspecified-length declarations, as they're a somewhat niche feature of C (in particular, they're not used much--or at all?--in Apple's SDK headers). This should be pretty easy to implement (basically we just need to teach the importer that it's just a pointer), so there's a fairly high chance of it getting fixed if you file a bug report =)

2 Likes

@scanon Thanks a lot for patiently explaining.

Bug report: https://bugs.swift.org/browse/SR-12263

@scanon
Edit: Corrected the bug report link (sorry about that)

2 Likes

Doing a little archaeology, I find the following (lib/ClangImporter/ImportType.cpp:487):

    ImportResult VisitArrayType(const clang::ArrayType *type) {
      // FIXME: Array types will need to be mapped differently depending on
      // context.
      return Type();
    }

With the commit message (Dec. 2012) from @Douglas_Gregor "C array types effectively have different behavior in different contexts; don't try to map them now." So this may be a little bit thornier to resolve than I thought at first, but we should still still probably do it (but: I'm not entirely convinced that simply decaying them to Unsafe[Mutable]Pointer<T> isn't the best option).

3 Likes

@scanon Thanks a lot for investigating into it and updating on the issue!