Lưu ý khi porting C/C++ sang Java

5/5 - (1 vote)

Chả là thời gian vừa rồi tôi có cơ hội tiếp cận dự án porting ứng dụng trên macOS sang ứng dụng Android nên có tổng hợp lại để sau này dùng nếu cần hoặc hữu ích với ai đó đang tìm kiếm (thời điểm tôi viết tìm tiếng Anh & Việt rất hiếm, có lẽ đây là bài viết đầu tiên bằng tiếng Việt có cái nhìn tổng quan đến như vậy).

Có thể nó sẽ rất hữu ích khi chúng ta nghĩ, thiết kế hệ thống mới.

Porting có thể hiểu là việc convert phần mềm chạy nền tảng này sang nền tảng khác.

Ví dụ: convert app xử lý âm thanh chạy trên windows được viết bằng C/C++/Objective-C sang Android app được viết bằng Java.

Phần mềm Portable cũng bắt nguồn từ từ này, Portable nghĩa là linh động, di động, linh hoạt không cần cài cắm, có hẳn 1 trang cho các phần mềm dạng đó: portableapps.com

Xem qua các nội dung cần chú ý khi porting:

  1. Kiểu dữ liệu (data type)

  2. Pointer vs Reference vs Array vs Object

  3. Struct vs Class

  4. Cast (ép kiểu)

  5. So sánh UInt8 and uint8_t

Bắt đầu đi chi tiết:

Kiểu dữ liệu (data type)

Các ngôn ngữ như C, C++, Objective-C, Java rất quan trọng kiểu dữ liệu. Do đó việc đầu tiên phải chú ý đó là kiểu dữ liệu tương ứng.

Nếu không lưu đúng kiểu data thì sẽ gây ra chương trình bị lỗi.

vd: đáng lẽ phải lưu số 128 mà ta chỉ lưu số -1 thì sẽ gây ra lỗi nghiêm trọng trong các phép tính: cộng, trừ, nhân, chia.
(ở đây chúng ta ví dụ số 128 là vì trong Java: số nguyên lớn nhất 1 byte có thể chứa được là số nguyên 127, bạn phải chú ý điều này)

1. Các kiểu dữ liệu nguyên thuỷ có trong Java

Đầu tiên chúng ta xem thử trong Java có những kiểu gì.

Trong tiếng Anh họ dùng từ primitive, khi đọc các tài liệu tiếng Việt bạn có thể hiểu nó là kiểu dữ liệu nguyên thuỷ hoặc kiểu dữ liệu gốc. Vì ngoài kiểu primitive này ra Java còn có các kiểu dữ liệu reference hay đôi khi họ gọi là non-primitive. Nói qua loại reference này là 1 kiểu wrapper class bọc lấy kiểu primitive và thêm các phương thức tiện ích cho tiện thao tác.

Loại
primitive
Kích thướcGiải thíchLoại reference
tương ứng
byte1 bytedùng để chứa số: từ -128 đến 127Byte
short2 bytesdùng để chứa số: từ -32,768 đến 32,767Short
int4 bytesdùng để chứa số: từ -2,147,483,648 đến 2,147,483,647Integer
long8 bytesdùng để chứa số: từ -9,223,372,036,854,775,808 đến 9,223,372,036,854,775,807Long
float4 byteslưu số thập phân từ:
1.4e-45f đến 3.4028235e+38f (340,282,346,638,528,860,000,000,000,000,000,000,000.000000)
Float
double8 byteslưu số thập phânDouble
boolean1 bitchỉ lưu giá trị đúng sai – true falseBoolean
char2 bytes1 ký tự hoặc số từ 0 đến 65535
(có thể gán trực tiếp bằng kí tự hoặc số nguyên)
Character
Các kiểu dữ liệu trong Java

2. So sánh các kiểu dữ liệu tương ứng Java vs C/C++

JavaC/C++
byte (max: 127)char, int8 (max: 127)
short (max: 32767)uint8, Uint8 (max: 255)
int (max: 2147483647)uint16 (max: 65535)
int (max: 2147483647)int 4 bytes (max: 2147483647)
(tuỳ platform mà kiểu “int” này có “độ nặng” 2 bytes)
long (max: 9,223,372,036,854,775,807)uint32 (max: 4294967295)
floatfloat
doubledouble
booleanboolean
charchar
So sánh các kiểu dữ liệu

Chúng ta có thể lưu số nguyên trong nhiều kiểu dữ liệu khác nhau. (Số nguyên có 2 kiểu âm & dương)

Ví dụ có thể lưu số nguyên 1, 2, 3… bằng:
– kiểu int (rất hay dùng)
– hoặc kiểu byte
– hoặc kiểu short
– hoặc kiểu long
– và kể cả bằng kiểu float.

Nhưng có vấn đề đấy là:
Với những số nhỏ 1, 2, 3 thì không có sự khác biệt gì và chỉ khi muốn lưu những số lớn như tầm hàng tỷ thì có sự khác biệt cực lớn.

Ví dụ: bạn đang làm ứng dụng ngân hàng muốn lưu số tiền 5 tỷ vậy bạn chọn kiểu dữ liệu nào để lưu số nguyên 5,000,000,000?
Cụ thể ứng dụng đó được viết bằng Java thì bạn không thể lưu bằng byte, short, int được mà bạn phải lưu bằng kiểu long. Vì theo range này bạn lưu số 5 tỷ thì vượt quá sức của các kiểu byte, short, int và trong Java lại không có kiểu unsigned int. Kể cả có kiểu unsigned int như C/C++/Objective – C đi chăng nữa cũng không thể chứa hết vì unsigned int có range là: 0 ~ 4 294 967 295 (max gần 4 tỷ 3)

byte    -128 ~ 127
short   -32,768 ~ 32,767
int     -2,147,483,648 ~ 2,147,483,647

Do đó kiểu long là kiểu đúng nhất. Bạn có thể lưu được số tiền của người giàu nhất thế giới lên đến 9 tỷ tỷ.
Trường hợp lưu số lẻ thập phân trong tài khoản thì cần phải dùng kiểu float hoặc kiểu double.

3. Dùng số hệ Dec hay số hệ Hex?

1 số nguyên có thể viết ở các hệ khác nhau:

Ví dụ: số 255 hệ Dec có thể viết ở hệ Hex là 0xFF

Chúng ta có thể lưu số nguyên 255 theo kiểu này:

int my_var = 0xFF giống với int my_var = 255

Do đó 2 cách viết này là hoàn toàn giống nhau, dùng cách nào đó là tuỳ bạn.

Pointer vs Reference vs Array vs Object

Trong Java không có con trỏ nên muốn dùng theo phong cách con trỏ C/C++/Objective-C thì chúng ta phải dùng đối tượng hoặc mảng thay thế. Nếu dùng đối tượng hoặc mảng thì ta có thể hiểu là đang dùng tham chiếu. Tương tự cách dùng &abc hay *xyz.

Trong C, C++:

  • &abc là lấy địa chỉ 1 biến abc
  • *xyz là lấy ra giá trị của vùng nhớ mà con trỏ xyz trỏ đến.
  • C/C++ array chính là 1 con trỏ, mặc định con trỏ này trỏ vào array[0]

Struct vs Class

Trong Java không có struct nên muốn dùng theo phong cách C/C++ thì chúng ta có thể dùng static inner class

Cast (ép kiểu)

Khi chuyển các kiểu dữ liệu với nhau ta mới cần cast.

Nếu chuyển byte sang int thì làm như sau: int so_nguyen = abc & 0xFF

Nếu chỉ thao tác trên cùng kiểu dữ liệu thì không cần cast, byte thì dữ nguyên byte, int thì giữ nguyên int (điều này rất quan trọng)

So sánh UInt8 and uint8_t

kiểu nào có “_t” đằng sau là portable tức là có thể chạy multi-platform mà không gặp vấn đề gì về kiểu dữ liệu.

uint8_t đảm bảo rằng biến đang được khai báo luôn là số nguyên 8 bits.

Tương tự cho kiểu uint16_t, uint32_t…

Lời kết

Porting ứng dụng từ macOS sang Android là một quá trình phức tạp và đòi hỏi sự chú ý đến nhiều yếu tố khác nhau. Tuy nhiên, nếu được thực hiện một cách đúng đắn, việc porting ứng dụng có thể mang lại nhiều lợi ích và giúp tăng cường trải nghiệm người dùng, giúp mở rộng thị trường tiềm năng cho ứng dụng.

Để đạt được mục tiêu porting ứng dụng thành công, cần phải có kế hoạch rõ ràng và cẩn thận với quá trình chuyển đổi mã nguồn và thiết kế giao diện. Việc sử dụng các công cụ và framework hỗ trợ cũng rất quan trọng trong quá trình này. Nếu không có kinh nghiệm về porting, bạn nên tìm kiếm sự giúp đỡ từ những chuyên gia hoặc công ty phát triển phần mềm. Liên hệ với dotrinh cũng là một ý tưởng tốt!

Tham khảo thêm

https://dotrinh.com/little-endian-unsinged-trong-java/

https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=msvc-170

https://stackoverflow.com/questions/16937459/whats-the-difference-between-uint8-and-uint8-t

https://www.cs.cornell.edu/courses/cs202/2002sp/JavaCcomparison.html

https://introcs.cs.princeton.edu/java/faq/c2java.html

https://stackoverflow.com/questions/2386772/what-is-the-difference-between-float-and-double

*Bài viết này sẽ được bổ sung thêm khi cần thiết.

Các bài viết không xem thì tiếc:

1 Comment

  1. Mời anh chị em đóng góp thêm bằng cách cmt trực tiếp trong post và chúng ta cùng thảo luận. Nếu hợp lý mình sẽ update trực tiếp bài viết để người khác có thể đọc được.

Thảo luận

This site uses Akismet to reduce spam. Learn how your comment data is processed.

5/5 - (1 vote)

Chả là thời gian vừa rồi tôi có cơ hội tiếp cận dự án porting ứng dụng trên macOS sang ứng dụng Android nên có tổng hợp lại để sau này dùng nếu cần hoặc hữu ích với ai đó đang tìm kiếm (thời điểm tôi viết tìm tiếng Anh & Việt rất hiếm, có lẽ đây là bài viết đầu tiên bằng tiếng Việt có cái nhìn tổng quan đến như vậy).

Có thể nó sẽ rất hữu ích khi chúng ta nghĩ, thiết kế hệ thống mới.

Porting có thể hiểu là việc convert phần mềm chạy nền tảng này sang nền tảng khác.

Ví dụ: convert app xử lý âm thanh chạy trên windows được viết bằng C/C++/Objective-C sang Android app được viết bằng Java.

Phần mềm Portable cũng bắt nguồn từ từ này, Portable nghĩa là linh động, di động, linh hoạt không cần cài cắm, có hẳn 1 trang cho các phần mềm dạng đó: portableapps.com

Xem qua các nội dung cần chú ý khi porting:

  1. Kiểu dữ liệu (data type)

  2. Pointer vs Reference vs Array vs Object

  3. Struct vs Class

  4. Cast (ép kiểu)

  5. So sánh UInt8 and uint8_t

Bắt đầu đi chi tiết:

Kiểu dữ liệu (data type)

Các ngôn ngữ như C, C++, Objective-C, Java rất quan trọng kiểu dữ liệu. Do đó việc đầu tiên phải chú ý đó là kiểu dữ liệu tương ứng.

Nếu không lưu đúng kiểu data thì sẽ gây ra chương trình bị lỗi.

vd: đáng lẽ phải lưu số 128 mà ta chỉ lưu số -1 thì sẽ gây ra lỗi nghiêm trọng trong các phép tính: cộng, trừ, nhân, chia.
(ở đây chúng ta ví dụ số 128 là vì trong Java: số nguyên lớn nhất 1 byte có thể chứa được là số nguyên 127, bạn phải chú ý điều này)

1. Các kiểu dữ liệu nguyên thuỷ có trong Java

Đầu tiên chúng ta xem thử trong Java có những kiểu gì.

Trong tiếng Anh họ dùng từ primitive, khi đọc các tài liệu tiếng Việt bạn có thể hiểu nó là kiểu dữ liệu nguyên thuỷ hoặc kiểu dữ liệu gốc. Vì ngoài kiểu primitive này ra Java còn có các kiểu dữ liệu reference hay đôi khi họ gọi là non-primitive. Nói qua loại reference này là 1 kiểu wrapper class bọc lấy kiểu primitive và thêm các phương thức tiện ích cho tiện thao tác.

Loại
primitive
Kích thướcGiải thíchLoại reference
tương ứng
byte1 bytedùng để chứa số: từ -128 đến 127Byte
short2 bytesdùng để chứa số: từ -32,768 đến 32,767Short
int4 bytesdùng để chứa số: từ -2,147,483,648 đến 2,147,483,647Integer
long8 bytesdùng để chứa số: từ -9,223,372,036,854,775,808 đến 9,223,372,036,854,775,807Long
float4 byteslưu số thập phân từ:
1.4e-45f đến 3.4028235e+38f (340,282,346,638,528,860,000,000,000,000,000,000,000.000000)
Float
double8 byteslưu số thập phânDouble
boolean1 bitchỉ lưu giá trị đúng sai – true falseBoolean
char2 bytes1 ký tự hoặc số từ 0 đến 65535
(có thể gán trực tiếp bằng kí tự hoặc số nguyên)
Character
Các kiểu dữ liệu trong Java

2. So sánh các kiểu dữ liệu tương ứng Java vs C/C++

JavaC/C++
byte (max: 127)char, int8 (max: 127)
short (max: 32767)uint8, Uint8 (max: 255)
int (max: 2147483647)uint16 (max: 65535)
int (max: 2147483647)int 4 bytes (max: 2147483647)
(tuỳ platform mà kiểu “int” này có “độ nặng” 2 bytes)
long (max: 9,223,372,036,854,775,807)uint32 (max: 4294967295)
floatfloat
doubledouble
booleanboolean
charchar
So sánh các kiểu dữ liệu

Chúng ta có thể lưu số nguyên trong nhiều kiểu dữ liệu khác nhau. (Số nguyên có 2 kiểu âm & dương)

Ví dụ có thể lưu số nguyên 1, 2, 3… bằng:
– kiểu int (rất hay dùng)
– hoặc kiểu byte
– hoặc kiểu short
– hoặc kiểu long
– và kể cả bằng kiểu float.

Nhưng có vấn đề đấy là:
Với những số nhỏ 1, 2, 3 thì không có sự khác biệt gì và chỉ khi muốn lưu những số lớn như tầm hàng tỷ thì có sự khác biệt cực lớn.

Ví dụ: bạn đang làm ứng dụng ngân hàng muốn lưu số tiền 5 tỷ vậy bạn chọn kiểu dữ liệu nào để lưu số nguyên 5,000,000,000?
Cụ thể ứng dụng đó được viết bằng Java thì bạn không thể lưu bằng byte, short, int được mà bạn phải lưu bằng kiểu long. Vì theo range này bạn lưu số 5 tỷ thì vượt quá sức của các kiểu byte, short, int và trong Java lại không có kiểu unsigned int. Kể cả có kiểu unsigned int như C/C++/Objective – C đi chăng nữa cũng không thể chứa hết vì unsigned int có range là: 0 ~ 4 294 967 295 (max gần 4 tỷ 3)

byte    -128 ~ 127
short   -32,768 ~ 32,767
int     -2,147,483,648 ~ 2,147,483,647

Do đó kiểu long là kiểu đúng nhất. Bạn có thể lưu được số tiền của người giàu nhất thế giới lên đến 9 tỷ tỷ.
Trường hợp lưu số lẻ thập phân trong tài khoản thì cần phải dùng kiểu float hoặc kiểu double.

3. Dùng số hệ Dec hay số hệ Hex?

1 số nguyên có thể viết ở các hệ khác nhau:

Ví dụ: số 255 hệ Dec có thể viết ở hệ Hex là 0xFF

Chúng ta có thể lưu số nguyên 255 theo kiểu này:

int my_var = 0xFF giống với int my_var = 255

Do đó 2 cách viết này là hoàn toàn giống nhau, dùng cách nào đó là tuỳ bạn.

Pointer vs Reference vs Array vs Object

Trong Java không có con trỏ nên muốn dùng theo phong cách con trỏ C/C++/Objective-C thì chúng ta phải dùng đối tượng hoặc mảng thay thế. Nếu dùng đối tượng hoặc mảng thì ta có thể hiểu là đang dùng tham chiếu. Tương tự cách dùng &abc hay *xyz.

Trong C, C++:

  • &abc là lấy địa chỉ 1 biến abc
  • *xyz là lấy ra giá trị của vùng nhớ mà con trỏ xyz trỏ đến.
  • C/C++ array chính là 1 con trỏ, mặc định con trỏ này trỏ vào array[0]

Struct vs Class

Trong Java không có struct nên muốn dùng theo phong cách C/C++ thì chúng ta có thể dùng static inner class

Cast (ép kiểu)

Khi chuyển các kiểu dữ liệu với nhau ta mới cần cast.

Nếu chuyển byte sang int thì làm như sau: int so_nguyen = abc & 0xFF

Nếu chỉ thao tác trên cùng kiểu dữ liệu thì không cần cast, byte thì dữ nguyên byte, int thì giữ nguyên int (điều này rất quan trọng)

So sánh UInt8 and uint8_t

kiểu nào có “_t” đằng sau là portable tức là có thể chạy multi-platform mà không gặp vấn đề gì về kiểu dữ liệu.

uint8_t đảm bảo rằng biến đang được khai báo luôn là số nguyên 8 bits.

Tương tự cho kiểu uint16_t, uint32_t…

Lời kết

Porting ứng dụng từ macOS sang Android là một quá trình phức tạp và đòi hỏi sự chú ý đến nhiều yếu tố khác nhau. Tuy nhiên, nếu được thực hiện một cách đúng đắn, việc porting ứng dụng có thể mang lại nhiều lợi ích và giúp tăng cường trải nghiệm người dùng, giúp mở rộng thị trường tiềm năng cho ứng dụng.

Để đạt được mục tiêu porting ứng dụng thành công, cần phải có kế hoạch rõ ràng và cẩn thận với quá trình chuyển đổi mã nguồn và thiết kế giao diện. Việc sử dụng các công cụ và framework hỗ trợ cũng rất quan trọng trong quá trình này. Nếu không có kinh nghiệm về porting, bạn nên tìm kiếm sự giúp đỡ từ những chuyên gia hoặc công ty phát triển phần mềm. Liên hệ với dotrinh cũng là một ý tưởng tốt!

Tham khảo thêm

https://dotrinh.com/little-endian-unsinged-trong-java/

https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=msvc-170

https://stackoverflow.com/questions/16937459/whats-the-difference-between-uint8-and-uint8-t

https://www.cs.cornell.edu/courses/cs202/2002sp/JavaCcomparison.html

https://introcs.cs.princeton.edu/java/faq/c2java.html

https://stackoverflow.com/questions/2386772/what-is-the-difference-between-float-and-double

*Bài viết này sẽ được bổ sung thêm khi cần thiết.

Các bài viết không xem thì tiếc:

Thảo luận

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Xem thêm
Ví dụ có đoạn khởi tạo như sau: textPaint =…
 
 
 
 
Facetime iPhone

Main Menu