Is there any difference between swift and C++ for `pid_t` type?

Hi,
I am trying to send pid_t type value from swift language application to kernel space through IOKit by using C++ library.

While I am printing 'pid_t' value in swift application it is showing proper value but it is not showing same value in C++ library function.

I have declared variable with type pid_t in both swift application and c++ library.

I tried same for other type variable like Int32 in swift and int in C++ library. Here values are showing properly.

Is there any difference between swift and C++ for pid_t type?
Answered by OOPer in 633103022

But I am facing with compilation error

When you assign Swift String into fixed-sized char array of C, Swift compiler does not help and you may need to call strlcpy (or some other byte transfer function if appropriate) explicitly.

Something like this:
Code Block
var event_info = ne_event_info_t(
lport: Int32(localEndpoint.port) ?? 0,
rport: Int32(remoteEndpoint.port) ?? 0,
ip_size: Int32(remoteEndpoint.hostname.count),
ip: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), //<-
pid: flow.pid,
direction: dir == 2 ? 1 : 0)
//To set Swift String into `char` array of C, you need to call `strlcpy`
_ = withUnsafeMutableBytes(of: &event_info.ip) {ipBuf in
strlcpy(ipBuf.baseAddress!.assumingMemoryBound(to: Int8.self),
remoteEndpoint.hostname,
ipBuf.count)
}


Is there any difference between swift and C++ for pid_t type?

Very unlikely. In Apple's platforms pid_t is an alias of int, and is imported as Int32.

While I am printing 'pid_t' value in swift application it is showing proper value but it is not showing same value in C++ library function.

I guess it might be the problem of how to show the values.
Can you show us your code showing the values and the example of the difference?
Thanks for reply. I am showing pid value using string format in swift and "%d" formatter in c++.
Following is the my swift application structure & function.
Code Block
struct ne_event_info_s {
  var lport: Int32
  var rport: Int32
  var ip_size: Int32
  var ip: String
  var pid: pid_t
  var direction : Int32
}
extension NEFilterFlow
{
  var sourceAppAuditTokenQ: audit_token_t? {
    guard
      let tokenData = self.sourceAppAuditToken,
      tokenData.count == MemoryLayout<audit_token_t>.size
    else { return nil }
    return tokenData.withUnsafeBytes { buf in
      buf.baseAddress!.assumingMemoryBound(to: audit_token_t.self).pointee
    }
  }
   
  var pid: pid_t {
    return audit_token_to_pid(sourceAppAuditTokenQ!)
  }
}
override func handleNewFlow(_ flow: NEFilterFlow) -> NEFilterNewFlowVerdict {
      guard let socketFlow = flow as? NEFilterSocketFlow,
         let remoteEndpoint = socketFlow.remoteEndpoint as? NWHostEndpoint,
         let localEndpoint = socketFlow.localEndpoint as? NWHostEndpoint else {
           return .allow()
       }
var event_info = ne_event_info_t(
                             lport: Int32(localEndpoint.port) ?? 0,
                             rport: Int32(remoteEndpoint.port) ?? 0,
                             ip_size: Int32(remoteEndpoint.hostname.count),
                             ip: String(remoteEndpoint.hostname),
                             pid: flow.pid,
                             direction: dir == 2 ? 1 : 0)
       os_log("event_info.lport = %@", String(event_info.lport))
       os_log("event_info.rport = %@", String(event_info.rport))
       os_log("event_info.ip_size = %@", String(event_info.ip_size))
       os_log("event_info.pid = %@", String(event_info.pid))
       os_log("Direction = %@", String(event_info.direction))
}

Following is C++ structure & function.

Code Block
typedef struct ne_event_info_s {
  int lport;
  int rport;
  int ip_size;
  unsigned char ip[16];
  pid_t pid;
  int direction;
} ne_event_info_t;
void handleNEEvent(ne_event_info_t *info,) {
  os_log("handleNEEvent: pid:%d, lport:%d,rport: %d\n", info->pid, info->lport,info->rport);
}




Thanks for showing your code. But I cannot see how you are passing a value of pid_t from Swift to C (or C to Swift).

Are you calling handleNEEvent from somewhere in Swift code?

One important point to check, your ne_event_info_s in Swift and your ne_event_info_s (or ne_event_info_t) in C++ are not layout compatible. That may very probably causing the issue.

How your ne_event_info_t in Swift is defined? If it was imported from C++ header, your Swift code would cause build-time error.

Are you calling handleNEEvent from somewhere in Swift code?
I am not calling handleNEEvent() directly. But I am passing 'neeventinfo_s' structure through IOKit in handleNewFlow() to my kernel space.


How your neeventinfo_t in Swift is defined? If it was imported from C++ header, your Swift code would cause build-time error.
I have defined two different structures with same variables in both swift code and kernel space.

I have defined two different structures with same variables in both swift code and kernel space.

As I already wrote, two structs are not the same.
Thanks for your response. Is there any way to define same & single structure in both swift and c?

Is there any way to define same & single structure in both swift and c?

Define the struct in a C-style header file, and import it into Swift using the Bridging-Header.
(As you are using C++ library, you may already have a bridging header, I think. You may need to modify it.)
Thanks for response and here issue in pid value change is due to 'var ip: String' in my swift code. I have declared ip as 'String' type in swift and 'unsigned char[16]' type in C.

Now I removed structure from swift and defined the struct in a C-style header file, and imported it into Swift using the Bridging-Header. I able to assign the values to all member variables in structure in C-style header file except for 'unsigned char ip[16]'

I tried to assign value to unsigned char ip[16] type in C-style header from swift as below

Code Block
let host: String = remoteEndpoint.hostname as String
event_info.ip = Array(host.utf8)


But I am facing with compilation error Cannot assign value of type 'Array<String.UTF8View.Element>' (aka 'Array<UInt8>') to type '(UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)'

Please help me to assign value to unsigned char[16] type from swift. Sample code and structure defnition already available in the thread.
Accepted Answer

But I am facing with compilation error

When you assign Swift String into fixed-sized char array of C, Swift compiler does not help and you may need to call strlcpy (or some other byte transfer function if appropriate) explicitly.

Something like this:
Code Block
var event_info = ne_event_info_t(
lport: Int32(localEndpoint.port) ?? 0,
rport: Int32(remoteEndpoint.port) ?? 0,
ip_size: Int32(remoteEndpoint.hostname.count),
ip: (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), //<-
pid: flow.pid,
direction: dir == 2 ? 1 : 0)
//To set Swift String into `char` array of C, you need to call `strlcpy`
_ = withUnsafeMutableBytes(of: &event_info.ip) {ipBuf in
strlcpy(ipBuf.baseAddress!.assumingMemoryBound(to: Int8.self),
remoteEndpoint.hostname,
ipBuf.count)
}


Is there any difference between swift and C++ for `pid_t` type?
 
 
Q