Gọi C / C ++ từ Python? [đóng cửa]

538
shoosh 2008-09-28 19:34.

Cách nhanh nhất để tạo liên kết Python với thư viện C hoặc C ++ là gì?

(Tôi đang sử dụng Windows nếu điều này quan trọng.)

12 answers

179
Ralph 2008-09-28 21:51.

Bạn nên xem qua Boost.Python . Đây là phần giới thiệu ngắn lấy từ trang web của họ:

Thư viện Boost Python là một khuôn khổ để giao tiếp Python và C ++. Nó cho phép bạn hiển thị nhanh chóng và liền mạch các hàm và đối tượng của lớp C ++ sang Python và ngược lại, không sử dụng công cụ đặc biệt - chỉ cần trình biên dịch C ++ của bạn. Nó được thiết kế để bọc các giao diện C ++ một cách không xâm phạm, do đó bạn không cần phải thay đổi mã C ++ để bọc nó, làm cho Boost.Python trở nên lý tưởng để hiển thị các thư viện của bên thứ 3 cho Python. Việc thư viện sử dụng các kỹ thuật lập trình siêu chương trình nâng cao đơn giản hóa cú pháp của nó cho người dùng, do đó mã gói trông giống như một loại ngôn ngữ định nghĩa giao diện khai báo (IDL).

684
Florian Bösch 2008-09-29 00:53.

mô-đun ctypes là một phần của thư viện tiêu chuẩn và do đó ổn định hơn và khả dụng rộng rãi hơn swig , luôn có xu hướng gây ra vấn đề cho tôi .

Với ctypes, bạn cần phải đáp ứng bất kỳ sự phụ thuộc vào thời gian biên dịch nào vào python và ràng buộc của bạn sẽ hoạt động trên bất kỳ python nào có ctypes, không chỉ tệp mà nó được biên dịch chống lại.

Giả sử bạn có một lớp mẫu C ++ đơn giản mà bạn muốn nói chuyện trong một tệp có tên foo.cpp:

#include <iostream>

class Foo{
    public:
        void bar(){
            std::cout << "Hello" << std::endl;
        }
};

Vì ctypes chỉ có thể nói chuyện với các hàm C, bạn cần cung cấp những hàm khai báo chúng là "C" bên ngoài

extern "C" {
    Foo* Foo_new(){ return new Foo(); }
    void Foo_bar(Foo* foo){ foo->bar(); }
}

Tiếp theo, bạn phải biên dịch nó vào một thư viện được chia sẻ

g++ -c -fPIC foo.cpp -o foo.o
g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

Và cuối cùng bạn phải viết trình bao bọc python của mình (ví dụ: trong fooWrapper.py)

from ctypes import cdll
lib = cdll.LoadLibrary('./libfoo.so')

class Foo(object):
    def __init__(self):
        self.obj = lib.Foo_new()

    def bar(self):
        lib.Foo_bar(self.obj)

Khi bạn có điều đó, bạn có thể gọi nó như

f = Foo()
f.bar() #and you will see "Hello" on the screen
59
Ben Hoffstein 2008-09-28 19:44.

Cách nhanh nhất để làm điều này là sử dụng SWIG .

Ví dụ từ hướng dẫn SWIG :

/* File : example.c */
int fact(int n) {
    if (n <= 1) return 1;
    else return n*fact(n-1);
}

Tệp giao diện:

/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern int fact(int n);
%}

extern int fact(int n);

Xây dựng mô-đun Python trên Unix:

swig -python example.i
gcc -fPIC -c example.c example_wrap.c -I/usr/local/include/python2.7
gcc -shared example.o example_wrap.o -o _example.so

Sử dụng:

>>> import example
>>> example.fact(5)
120

Lưu ý rằng bạn phải có python-dev. Ngoài ra, trong một số hệ thống, tệp tiêu đề python sẽ nằm trong /usr/include/python2.7 dựa trên cách bạn đã cài đặt nó.

Từ hướng dẫn:

SWIG là một trình biên dịch C ++ khá hoàn chỉnh với sự hỗ trợ cho hầu hết các tính năng của ngôn ngữ. Điều này bao gồm tiền xử lý, con trỏ, lớp, kế thừa và thậm chí cả các mẫu C ++. SWIG cũng có thể được sử dụng để đóng gói các cấu trúc và lớp thành các lớp proxy bằng ngôn ngữ đích - thể hiện chức năng cơ bản một cách rất tự nhiên.

50
Antonello 2014-05-26 22:30.

Tôi đã bắt đầu hành trình của mình trong liên kết Python <-> C ++ từ trang này, với mục tiêu liên kết các kiểu dữ liệu cấp cao (vectơ STL đa chiều với danh sách Python) :-)

Sau khi thử các giải pháp dựa trên cả ctypes và boost.python (và không phải là kỹ sư phần mềm), tôi thấy chúng phức tạp khi yêu cầu ràng buộc các kiểu dữ liệu cấp cao, trong khi tôi thấy SWIG đơn giản hơn nhiều cho những trường hợp như vậy.

Vì vậy, ví dụ này sử dụng SWIG và nó đã được thử nghiệm trong Linux (nhưng SWIG có sẵn và cũng được sử dụng rộng rãi trong Windows).

Mục tiêu là làm cho một hàm C ++ có sẵn cho Python, lấy một ma trận ở dạng vectơ 2D STL và trả về giá trị trung bình của mỗi hàng (dưới dạng vectơ STL 1D).

Mã trong C ++ ("code.cpp") như sau:

#include <vector>
#include "code.h"

using namespace std;

vector<double> average (vector< vector<double> > i_matrix) {

  // Compute average of each row..
  vector <double> averages;
  for (int r = 0; r < i_matrix.size(); r++){
    double rsum = 0.0;
    double ncols= i_matrix[r].size();
    for (int c = 0; c< i_matrix[r].size(); c++){
      rsum += i_matrix[r][c];
    }
    averages.push_back(rsum/ncols);
  }
  return averages;
}

Tiêu đề tương đương ("code.h") là:

#ifndef _code
#define _code

#include <vector>

std::vector<double> average (std::vector< std::vector<double> > i_matrix);

#endif

Đầu tiên chúng tôi biên dịch mã C ++ để tạo tệp đối tượng:

g++ -c -fPIC code.cpp

Sau đó, chúng tôi xác định tệp định nghĩa giao diện SWIG ("code.i") cho các hàm C ++ của chúng tôi.

%module code
%{
#include "code.h"
%}
%include "std_vector.i"
namespace std {

  /* On a side note, the names VecDouble and VecVecdouble can be changed, but the order of first the inner vector matters! */
  %template(VecDouble) vector<double>;
  %template(VecVecdouble) vector< vector<double> >;
}

%include "code.h"

Sử dụng SWIG, chúng tôi tạo mã nguồn giao diện C ++ từ tệp định nghĩa giao diện SWIG ..

swig -c++ -python code.i

Cuối cùng, chúng tôi biên dịch tệp nguồn giao diện C ++ đã tạo và liên kết mọi thứ với nhau để tạo một thư viện chia sẻ có thể nhập trực tiếp bằng Python (vấn đề "_"):

g++ -c -fPIC code_wrap.cxx  -I/usr/include/python2.7 -I/usr/lib/python2.7
g++ -shared -Wl,-soname,_code.so -o _code.so code.o code_wrap.o

Bây giờ chúng ta có thể sử dụng hàm trong các tập lệnh Python:

#!/usr/bin/env python

import code
a= [[3,5,7],[8,10,12]]
print a
b = code.average(a)
print "Assignment done"
print a
print b
43
Tom Wenseleers 2016-07-24 03:53.

Ngoài ra còn có pybind11, giống như một phiên bản nhẹ của Boost.Python và tương thích với tất cả các trình biên dịch C ++ hiện đại:

https://pybind11.readthedocs.io/en/latest/

24
Wim Lavrijsen 2018-03-06 13:02.

Đối với C ++ hiện đại, hãy sử dụng cppyy: http://cppyy.readthedocs.io/en/latest/

Nó dựa trên Cling, trình thông dịch C ++ cho Clang / LLVM. Các ràng buộc ở thời điểm chạy và không cần thêm ngôn ngữ trung gian. Nhờ có Clang, nó hỗ trợ C ++ 17.

Cài đặt nó bằng cách sử dụng pip:

    $ pip install cppyy

Đối với các dự án nhỏ, chỉ cần tải thư viện có liên quan và các tiêu đề mà bạn quan tâm. Ví dụ: lấy mã từ ví dụ ctypes là luồng này, nhưng chia thành các phần tiêu đề và mã:

    $ cat foo.h
    class Foo {
    public:
        void bar();
    };

    $ cat foo.cpp
    #include "foo.h"
    #include <iostream>

    void Foo::bar() { std::cout << "Hello" << std::endl; }

Biên dịch nó:

    $ g++ -c -fPIC foo.cpp -o foo.o
    $ g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

và sử dụng nó:

    $ python
    >>> import cppyy
    >>> cppyy.include("foo.h")
    >>> cppyy.load_library("foo")
    >>> from cppyy.gbl import Foo
    >>> f = Foo()
    >>> f.bar()
    Hello
    >>>

Các dự án lớn được hỗ trợ với tính năng tự động tải thông tin phản ánh đã chuẩn bị và các đoạn cmake để tạo chúng, để người dùng các gói đã cài đặt có thể chạy một cách đơn giản:

    $ python
    >>> import cppyy
    >>> f = cppyy.gbl.Foo()
    >>> f.bar()
    Hello
    >>>

Nhờ LLVM, có thể có các tính năng nâng cao, chẳng hạn như tạo mẫu tự động. Để tiếp tục ví dụ:

    >>> v = cppyy.gbl.std.vector[cppyy.gbl.Foo]()
    >>> v.push_back(f)
    >>> len(v)
    1
    >>> v[0].bar()
    Hello
    >>>

Lưu ý: Tôi là tác giả của cppyy.

13
mrgloom 2013-11-06 00:39.

Tôi nghĩ cffi cho python có thể là một lựa chọn.

Mục đích là để gọi mã C từ Python. Bạn sẽ có thể làm như vậy mà không cần học ngôn ngữ thứ 3: mọi ngôn ngữ thay thế đều yêu cầu bạn học ngôn ngữ riêng của họ (Cython, SWIG) hoặc API (ctypes). Vì vậy, chúng tôi đã cố gắng giả định rằng bạn biết Python và C và giảm thiểu các bit bổ sung của API mà bạn cần học.

http://cffi.readthedocs.org/en/release-0.7/

8
Jadav Bheda 2015-08-28 20:38.

Câu hỏi là làm thế nào để gọi một hàm C từ Python, nếu tôi hiểu đúng. Sau đó, đặt cược tốt nhất là Ctypes (BTW di động trên tất cả các biến thể của Python).

>>> from ctypes import *
>>> libc = cdll.msvcrt
>>> print libc.time(None)
1438069008
>>> printf = libc.printf
>>> printf("Hello, %s\n", "World!")
Hello, World!
14
>>> printf("%d bottles of beer\n", 42)
42 bottles of beer
19

Để có hướng dẫn chi tiết, bạn có thể tham khảo bài viết trên blog của tôi .

6
nicodjimenez 2015-12-30 07:27.

Cython chắc chắn là con đường để đi, trừ khi bạn dự kiến ​​viết trình bao bọc Java, trong trường hợp đó SWIG có thể thích hợp hơn.

Tôi khuyên bạn nên sử dụng runcythontiện ích dòng lệnh, nó giúp quá trình sử dụng Cython cực kỳ dễ dàng. Nếu bạn cần truyền dữ liệu có cấu trúc sang C ++, hãy xem thư viện protobuf của Google, nó rất tiện lợi.

Đây là một ví dụ tối thiểu mà tôi đã thực hiện sử dụng cả hai công cụ:

https://github.com/nicodjimenez/python2cpp

Hy vọng nó có thể là một điểm khởi đầu hữu ích.

5
Yaroslav Nikitenko 2015-04-25 07:23.

Trước tiên, bạn nên quyết định mục đích cụ thể của bạn là gì. Tài liệu Python chính thức về mở rộng và nhúng trình thông dịch Python đã được đề cập ở trên, tôi có thể thêm một cái nhìn tổng quan về các phần mở rộng nhị phân . Các trường hợp sử dụng có thể được chia thành 3 loại:

  • mô-đun tăng tốc : để chạy nhanh hơn so với mã Python thuần tương đương chạy trong CPython.
  • mô-đun trình bao bọc : để hiển thị các giao diện C hiện có với mã Python.
  • truy cập hệ thống cấp thấp : để truy cập các tính năng cấp thấp hơn của thời gian chạy CPython, hệ điều hành hoặc phần cứng cơ bản.

Để cung cấp một số góc nhìn rộng hơn cho những người quan tâm khác và vì câu hỏi ban đầu của bạn hơi mơ hồ ("với thư viện C hoặc C ++"), tôi nghĩ thông tin này có thể thú vị với bạn. Trên liên kết ở trên, bạn có thể đọc về nhược điểm của việc sử dụng phần mở rộng nhị phân và các lựa chọn thay thế của nó.

Ngoài các câu trả lời khác được đề xuất, nếu bạn muốn có một mô-đun tăng tốc, bạn có thể thử Numba . Nó hoạt động "bằng cách tạo mã máy được tối ưu hóa bằng cách sử dụng cơ sở hạ tầng trình biên dịch LLVM tại thời điểm nhập, thời gian chạy hoặc tĩnh (sử dụng công cụ pycc đi kèm)".

ví dụ về pybind11 có thể chạy được tối thiểu

pybind11 trước đây đã được đề cập tại https://stackoverflow.com/a/38542539/895245 nhưng tôi muốn đưa ra ở đây một ví dụ sử dụng cụ thể và một số thảo luận thêm về việc triển khai.

Tất cả và tất cả, tôi thực sự khuyên bạn nên sử dụng pybind11 vì nó thực sự dễ sử dụng: bạn chỉ cần bao gồm một tiêu đề và sau đó pybind11 sử dụng phép mẫu để kiểm tra lớp C ++ mà bạn muốn hiển thị với Python và thực hiện điều đó một cách minh bạch.

Nhược điểm của phép thuật mẫu này là nó làm chậm quá trình biên dịch ngay lập tức thêm vài giây vào bất kỳ tệp nào sử dụng pybind11, hãy xem ví dụ điều tra được thực hiện về vấn đề này . PyTorch đồng ý . Một đề xuất để khắc phục vấn đề này đã được đưa ra tại:https://github.com/pybind/pybind11/pull/2445

Dưới đây là một ví dụ có thể chạy được tối thiểu để cho bạn cảm giác pybind11 tuyệt vời như thế nào:

class_test.cpp

#include <string>

#include <pybind11/pybind11.h>

struct ClassTest {
    ClassTest(const std::string &name) : name(name) { }
    void setName(const std::string &name_) { name = name_; }
    const std::string &getName() const { return name; }
    std::string name;
};

namespace py = pybind11;

PYBIND11_PLUGIN(class_test) {
    py::module m("my_module", "pybind11 example plugin");
    py::class_<ClassTest>(m, "ClassTest")
        .def(py::init<const std::string &>())
        .def("setName", &ClassTest::setName)
        .def("getName", &ClassTest::getName)
        .def_readwrite("name", &ClassTest::name);
    return m.ptr();
}

class_test_main.py

#!/usr/bin/env python3

import class_test

my_class_test = class_test.ClassTest("abc");
print(my_class_test.getName())
my_class_test.setName("012")
print(my_class_test.getName())
assert(my_class_test.getName() == my_class_test.name)

Biên dịch và chạy:

#!/usr/bin/env bash
set -eux
g++ `python3-config --cflags` -shared -std=c++11 -fPIC class_test.cpp \
  -o class_test`python3-config --extension-suffix` `python3-config --libs`
./class_test_main.py

Ví dụ này cho thấy cách pybind11 cho phép bạn dễ dàng hiển thị lớp ClassTestC ++ sang Python! Compilation tạo ra một file có tên class_test.cpython-36m-x86_64-linux-gnu.sođó class_test_main.pytự động nhặt như là điểm định nghĩa cho các class_testmô-đun natively xác định.

Có lẽ việc nhận ra điều này tuyệt vời như thế nào chỉ chìm vào nếu bạn cố gắng làm điều tương tự bằng tay với API Python gốc, hãy xem ví dụ này về việc làm điều đó, có mã nhiều hơn gấp 10 lần: https://github.com/cirosantilli/python-cheat/blob/4f676f62e87810582ad53b2fb426b74eae52aad5/py_from_c/pure.cTrên ví dụ đó, bạn có thể thấy cách mã C phải xác định rõ ràng từng chút một và rõ ràng lớp Python với tất cả thông tin mà nó chứa (thành viên, phương thức, siêu dữ liệu khác ...). Xem thêm:

  • Phần mở rộng python-C ++ có thể nhận một đối tượng C ++ và gọi hàm thành viên của nó không?
  • Hiển thị một phiên bản lớp C ++ với trình thông dịch nhúng python
  • Một ví dụ đầy đủ và tối thiểu cho một lớp (không phải phương thức) với Phần mở rộng Python C?
  • Nhúng Python trong C ++ và gọi các phương thức từ mã C ++ với Boost.Python
  • Kế thừa trong phần mở rộng Python C ++

pybind11 tuyên bố là tương tự như Boost.Pythonđã được đề cập tạihttps://stackoverflow.com/a/145436/895245 nhưng tối thiểu hơn vì nó được giải phóng khỏi sự cồng kềnh của dự án Boost:

pybind11 là một thư viện nhẹ chỉ dành cho tiêu đề, hiển thị các loại C ++ trong Python và ngược lại, chủ yếu để tạo các liên kết Python của mã C ++ hiện có. Mục tiêu và cú pháp của nó tương tự như thư viện Boost.Python tuyệt vời của David Abrahams: để giảm thiểu mã soạn sẵn trong các mô-đun mở rộng truyền thống bằng cách suy ra thông tin loại bằng cách sử dụng nội quan thời gian biên dịch.

Vấn đề chính với Boost.Python — và lý do tạo ra một dự án tương tự như vậy — là Boost. Boost là một bộ thư viện tiện ích cực kỳ lớn và phức tạp, hoạt động với hầu hết mọi trình biên dịch C ++ đang tồn tại. Khả năng tương thích này có giá của nó: các thủ thuật và cách giải quyết mẫu phức tạp là cần thiết để hỗ trợ các mẫu trình biên dịch lâu đời nhất và nhộn nhịp nhất. Giờ đây, các trình biên dịch tương thích với C ++ 11 đã được phổ biến rộng rãi, cỗ máy nặng nề này đã trở thành một phụ thuộc quá lớn và không cần thiết.

Hãy coi thư viện này như một phiên bản Boost.Python nhỏ bé khép kín với mọi thứ được loại bỏ không liên quan đến việc tạo ràng buộc. Không có chú thích, các tệp tiêu đề lõi chỉ yêu cầu ~ 4K dòng mã và phụ thuộc vào Python (2.7 hoặc 3.x, hoặc PyPy2.7> = 5.7) và thư viện chuẩn C ++. Việc triển khai nhỏ gọn này có thể thực hiện được nhờ một số tính năng mới của ngôn ngữ C ++ 11 (cụ thể là: bộ giá trị, hàm lambda và các mẫu đa dạng). Kể từ khi được tạo ra, thư viện này đã phát triển vượt ra ngoài Boost.Python theo nhiều cách, dẫn đến mã ràng buộc đơn giản hơn đáng kể trong nhiều tình huống phổ biến.

pybind11 cũng là giải pháp thay thế không có nguồn gốc duy nhất được làm nổi bật bởi tài liệu ràng buộc Microsoft Python C hiện tại tại: https://docs.microsoft.com/en-us/visualstudio/python/working-with-c-cpp-python-in-visual-studio?view=vs-2019( lưu trữ ).

Đã thử nghiệm trên Ubuntu 18.04, pybind11 2.0.1, Python 3.6.8, GCC 7.4.0.

3
Garfield 2019-12-19 23:56.

Tôi yêu cppyy, nó giúp bạn dễ dàng mở rộng Python bằng mã C ++, tăng đáng kể hiệu suất khi cần thiết.

Nó mạnh mẽ và thực sự rất đơn giản để sử dụng,

đây là một ví dụ về cách bạn có thể tạo một mảng numpy và chuyển nó vào một hàm thành viên lớp trong C ++.

cppyy_test.py

import cppyy
import numpy as np
cppyy.include('Buffer.h')


s = cppyy.gbl.Buffer()
numpy_array = np.empty(32000, np.float64)
s.get_numpy_array(numpy_array.data, numpy_array.size)
print(numpy_array[:20])

Buffer.h

struct Buffer {
  void get_numpy_array(double *ad, int size) {
    for( long i=0; i < size; i++)
        ad[i]=i;
  }
};

Bạn cũng có thể tạo một mô-đun Python rất dễ dàng (với CMake), bằng cách này bạn sẽ tránh phải biên dịch lại mã C ++ mọi lúc.

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

BoJack Horseman vẫn gan ruột và gan dạ hơn bao giờ hết trong phần 3

BoJack Horseman vẫn gan ruột và gan dạ hơn bao giờ hết trong phần 3

BoJack Horseman (Ảnh: Netflix) BoJack Horseman bắt đầu mùa thứ ba với sự xuất hiện của nhân vật tiêu biểu, người vẫn đang theo đuổi những lời khen ngợi từ giới phê bình trong một nỗ lực tuyệt vọng để tìm ra ý nghĩa trong cuộc sống của mình. Mùa thứ hai về số phận bi kịch của Raphael Bob-Waksberg dày đặc những trò đùa cũng như tuyệt vọng.

Xem cách tính năng lái tự động cập nhật của Tesla bùng phát như thế nào khi bạn bỏ qua các cảnh báo của nó

Xem cách tính năng lái tự động cập nhật của Tesla bùng phát như thế nào khi bạn bỏ qua các cảnh báo của nó

Bản nâng cấp Phiên bản 8.0 gần đây của Tesla đối với hệ thống Lái xe tự động được thiết kế để cải thiện hệ thống và mối quan hệ của nó với người lái.

UnREAL, Chương trình Truyền hình Về Truyền hình Thực tế Chúng tôi Không biết Chúng tôi Cần

UnREAL, Chương trình Truyền hình Về Truyền hình Thực tế Chúng tôi Không biết Chúng tôi Cần

Chắc chắn khi con cái chúng ta xem lại các chương trình chúng ta đã xem vào khoảng năm 2015, chúng sẽ thấy UnREAL, một chương trình truyền hình mới chiếu vào tối Thứ Hai của Lifetime — bạn sẽ thấy đúng lúc, sẽ phát sóng ngay sau khi The Bachelor kết thúc — như một chương trình không thể được thực hiện vào bất kỳ thời điểm nào khác trong lịch sử truyền hình, nhưng một chương trình cảm thấy cần thiết để xem bây giờ. UnREAL có sự tham gia của Shiri Appleby trong vai Rachel, một nhà sản xuất truyền hình cho một chương trình về cơ bản là The Bachelor, mặc dù trong thế giới này, nó được gọi là Vĩnh viễn.

Sau tất cả, Josh Trank sẽ không đạo diễn bộ phim tuyển tập Star Wars thứ hai

Sau tất cả, Josh Trank sẽ không đạo diễn bộ phim tuyển tập Star Wars thứ hai

Thông báo chính thức đến trực tiếp từ trang web của Star Wars: Fantastic Four, đạo diễn Josh Trank, một người bí ẩn không xuất hiện tại đại hội Star Wars Celebration gần đây, sẽ không chỉ đạo phần hai Star Wars Anthology. Đây là tuyên bố được đăng ngày hôm qua: Tất cả thực sự là ngôn ngữ rất lịch sự, nhưng một bài báo của Hollywood Reporter cho thấy tất cả đều không tốt ở hậu trường, gọi sự ra đi là "một vụ sa thải" một phần dựa trên "hành vi bất thường" của Trank trong khi quay Fantastic Four: The Bài báo trích dẫn các nguồn gọi là Trank “đôi khi thiếu quyết đoán và thiếu sáng tạo,” và lưu ý rằng Fantastic Four, khởi chiếu vào ngày 7 tháng 8, đã được khởi động lại vào cuối tháng 4.

Edwin McCain ra mắt Grand Ole Opry: Quay cảnh hậu trường với nhạc sĩ 'I'll Be'

Edwin McCain ra mắt Grand Ole Opry: Quay cảnh hậu trường với nhạc sĩ 'I'll Be'

McCain, người đang làm việc cho một album mới, lần đầu tiên bước vào vòng kết nối vào tối thứ Sáu ở Nashville

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Tôi viết như thế nào

Tôi viết như thế nào

Đối với tôi, mọi thứ là về dòng đầu tiên đó và nó sẽ đưa bạn đến đâu. Một số nhà văn bị điều khiển bởi cốt truyện, sự sắp xếp tinh tế của các quân cờ, trong khi những người khác bị lôi cuốn bởi một nhân vật và khả năng thực hiện một cuộc hành trình với một người bạn hư cấu mới.

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Language